Data Exploration and Wrangling
The first step in performing any data analysis is to explore the data.
For example, we might want to better understand the variables included in the data, as we may learn about important details about the data that we should keep in mind as we try to predict our outcome variable.
First, let’s just get a general sense of our data. We can do that using the glimpse() function of the dplyr package (it is also in the tibble package).
We will also use the %>% pipe, which can be used to define the input for later sequential steps.
This will make more sense when we have multiple sequential steps using the same data object.
To use the pipe notation we need to install and load dplyr as well.
For example, here we start with pm data object and “pipe” the object into as input into the glimpse() function. The output is is an overview of what is in the pm object such as the number of rows and columns, all the column names, the data types for each column and the first view values in each column. The output below is scrollable so you can see everything from the glimpse() function.
Rows: 876
Columns: 50
$ id <dbl> 1003.001, 1027.000, 1033.100, 1049.100, 1…
$ value <dbl> 9.597647, 10.800000, 11.212174, 11.659091…
$ fips <dbl> 1003, 1027, 1033, 1049, 1055, 1069, 1073,…
$ lat <dbl> 30.49800, 33.28126, 34.75878, 34.28763, 3…
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85.9683…
$ state <chr> "Alabama", "Alabama", "Alabama", "Alabama…
$ county <chr> "Baldwin", "Clay", "Colbert", "DeKalb", "…
$ city <chr> "Fairhope", "Ashland", "Muscle Shoals", "…
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 8.534772, 9…
$ zcta <dbl> 36532, 36251, 35660, 35962, 35901, 36303,…
$ zcta_area <dbl> 190980522, 374132430, 16716984, 203836235…
$ zcta_pop <dbl> 27829, 5103, 9042, 8300, 20045, 30217, 90…
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038, 5.78…
$ imp_a1000 <dbl> 1.4096021, 0.8531574, 11.1448962, 3.86764…
$ imp_a5000 <dbl> 3.3360118, 0.9851479, 15.1786154, 1.23114…
$ imp_a10000 <dbl> 1.9879187, 0.5208189, 9.7253870, 1.031646…
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 0.973044…
$ county_area <dbl> 4117521611, 1564252280, 1534877333, 20126…
$ county_pop <dbl> 182265, 13932, 54428, 71109, 104430, 1015…
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 3.721489, 5…
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 8.517193, 9…
$ log_pri_length_10000 <dbl> 9.210340, 9.210340, 9.274303, 10.409411, …
$ log_pri_length_15000 <dbl> 9.630228, 9.615805, 9.658899, 11.173626, …
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 11.90959, 1…
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 7.310155, 8…
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 8.585843, 9…
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 10.21420…
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 11.50894, 1…
$ log_prisec_length_15000 <dbl> 12.205723, 12.042963, 13.282656, 12.35366…
$ log_prisec_length_25000 <dbl> 13.41395, 12.79980, 13.79973, 13.55979, 1…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.573127301, 0.…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.581917457, 3.…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.887665, 4…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, 0.000…
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, 3.350…
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.171920, 4…
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 35.330814…
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 40.718…
$ nohs <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1, 2.7,…
$ somehs <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 17.1, …
$ hs <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, 37.2,…
$ somecollege <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, 23.5,…
$ associate <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, 8.0, …
$ bachelor <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.9, 17…
$ grad <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, 8.7, …
$ pov <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25.5, 7…
$ hs_orless <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, 61.4,…
$ urc2013 <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ urc2006 <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ aod <dbl> 37.36364, 34.81818, 36.00000, 33.08333, 4…
We can see that there are 876 monitors (rows) and that we have 50 total variables (columns) - one of which is the outcome variable. In this case, the outcome variable is called value.
Notice that some of the variables that we would think of as factors (or categorical data) are currently of class character as indicated by the <chr> just to the right of the column names/variable names in the glimpse() output. This means that the variable values are character strings, such as words or phrases.
The other variables are of class <dbl>, which stands for double precision which indicates that the are numeric and that they have decimal values. In contrast, one could have integer values which would not allow for decimal numbers. Here is a link for more information on double precision numeric values.
Another common data class is factor which is abbreviated like this: <fct>. A factor is something that has unique levels but there is no appreciable order to the levels. For example we can have a numeric value that is just an id that we want to be interpreted as just a unique level and not as the number that it would typically indicate. This would be useful for several of our variables:
- the monitor ID (
id)
- the Federal Information Processing Standard number for the county where the monitor was located (
fips)
- the zip code tabulation area (
zcta)
None of the values actually have any real numeric meaning, so we want to make sure that R does not interpret them as if they do.
So let’s convert these variables into factors. We can do this using the across() function of the dplyr package and the as.factor() base function. The across() function has two main arguments: (i) the columns you want to operate on and (ii) the function or list of functions to apply to each column.
In this case, we are also using the magrittr assignment pipe or double pipe that looks like this %<>% of the magrittr package. This allows us use the pm data as input, but also reassigns the output to the same data object name.
Rows: 876
Columns: 50
$ id <fct> 1003.001, 1027.0001, 1033.1002, 1049.1003…
$ value <dbl> 9.597647, 10.800000, 11.212174, 11.659091…
$ fips <fct> 1003, 1027, 1033, 1049, 1055, 1069, 1073,…
$ lat <dbl> 30.49800, 33.28126, 34.75878, 34.28763, 3…
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85.9683…
$ state <chr> "Alabama", "Alabama", "Alabama", "Alabama…
$ county <chr> "Baldwin", "Clay", "Colbert", "DeKalb", "…
$ city <chr> "Fairhope", "Ashland", "Muscle Shoals", "…
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 8.534772, 9…
$ zcta <fct> 36532, 36251, 35660, 35962, 35901, 36303,…
$ zcta_area <dbl> 190980522, 374132430, 16716984, 203836235…
$ zcta_pop <dbl> 27829, 5103, 9042, 8300, 20045, 30217, 90…
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038, 5.78…
$ imp_a1000 <dbl> 1.4096021, 0.8531574, 11.1448962, 3.86764…
$ imp_a5000 <dbl> 3.3360118, 0.9851479, 15.1786154, 1.23114…
$ imp_a10000 <dbl> 1.9879187, 0.5208189, 9.7253870, 1.031646…
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 0.973044…
$ county_area <dbl> 4117521611, 1564252280, 1534877333, 20126…
$ county_pop <dbl> 182265, 13932, 54428, 71109, 104430, 1015…
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 3.721489, 5…
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 8.517193, 9…
$ log_pri_length_10000 <dbl> 9.210340, 9.210340, 9.274303, 10.409411, …
$ log_pri_length_15000 <dbl> 9.630228, 9.615805, 9.658899, 11.173626, …
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 11.90959, 1…
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 7.310155, 8…
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 8.585843, 9…
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 10.21420…
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 11.50894, 1…
$ log_prisec_length_15000 <dbl> 12.205723, 12.042963, 13.282656, 12.35366…
$ log_prisec_length_25000 <dbl> 13.41395, 12.79980, 13.79973, 13.55979, 1…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.573127301, 0.…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.581917457, 3.…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.887665, 4…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, 0.000…
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, 3.350…
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.171920, 4…
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 35.330814…
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 40.718…
$ nohs <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1, 2.7,…
$ somehs <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 17.1, …
$ hs <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, 37.2,…
$ somecollege <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, 23.5,…
$ associate <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, 8.0, …
$ bachelor <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.9, 17…
$ grad <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, 8.7, …
$ pov <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25.5, 7…
$ hs_orless <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, 61.4,…
$ urc2013 <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ urc2006 <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2,…
$ aod <dbl> 37.36364, 34.81818, 36.00000, 33.08333, 4…
Great! Now we can see that these variables are now factors as indicated by <fct> after the variable name.
Skim package
The skim() function of the skimr package is also really helpful for getting a general sense of your data. By design, it provides summary statistics about variables in the data set.
Notice how there is a column called n_missing about the number of values that are missing.
This is also indicated by the complete_rate variable (or missing/number of observations).
In our data set, it looks like our data do not contain any missing data.
Also notice how the function provides separate tables of summary statistics for each data type: character, factor and numeric.
Next, the n_unqiue column shows us the number of unique values for each of our columns. We can see that there are 49 states represented in the data.
We can see that for many variables there are many low values as the distribution shows two peaks, one near zero and another with a higher value.
This is true for the imp variables (measures of development), the nei variables (measures of emission sources) and the road density variables.
We can also see that the range of some of the variables is very large, in particular the area and population related variables.
Let’s take a look to see which states are included using the distinct() function of the dplyr package:
Scroll through the output:
It looks like “District of Columbia” is being included as a state. We can see that Alaska and Hawaii are not included in the data.
Let’s also take a look to see how many monitors there are in a few cities. We can use the filter() function of the dplyr package to do so. For example, let’s look at Albuquerque, New Mexico.
# A tibble: 2 x 50
id value fips lat lon state county city CMAQ zcta zcta_area
<fct> <dbl> <fct> <dbl> <dbl> <chr> <chr> <chr> <dbl> <fct> <dbl>
1 3500… 5.98 35001 35.1 -107. New … Berna… Albu… 10.1 87109 26199125
2 3500… 5.91 35001 35.1 -107. New … Berna… Albu… 10.1 87108 15224438
# … with 39 more variables: zcta_pop <dbl>, imp_a500 <dbl>, imp_a1000 <dbl>,
# imp_a5000 <dbl>, imp_a10000 <dbl>, imp_a15000 <dbl>, county_area <dbl>,
# county_pop <dbl>, log_dist_to_prisec <dbl>, log_pri_length_5000 <dbl>,
# log_pri_length_10000 <dbl>, log_pri_length_15000 <dbl>,
# log_pri_length_25000 <dbl>, log_prisec_length_500 <dbl>,
# log_prisec_length_1000 <dbl>, log_prisec_length_5000 <dbl>,
# log_prisec_length_10000 <dbl>, log_prisec_length_15000 <dbl>,
# log_prisec_length_25000 <dbl>, log_nei_2008_pm25_sum_10000 <dbl>,
# log_nei_2008_pm25_sum_15000 <dbl>, log_nei_2008_pm25_sum_25000 <dbl>,
# log_nei_2008_pm10_sum_10000 <dbl>, log_nei_2008_pm10_sum_15000 <dbl>,
# log_nei_2008_pm10_sum_25000 <dbl>, popdens_county <dbl>,
# popdens_zcta <dbl>, nohs <dbl>, somehs <dbl>, hs <dbl>, somecollege <dbl>,
# associate <dbl>, bachelor <dbl>, grad <dbl>, pov <dbl>, hs_orless <dbl>,
# urc2013 <dbl>, urc2006 <dbl>, aod <dbl>
We can see that there were only two monitors in the city of Albuquerque in 2006. Let’s compare this with Baltimore.
# A tibble: 5 x 50
id value fips lat lon state county city CMAQ zcta zcta_area
<fct> <dbl> <fct> <dbl> <dbl> <chr> <chr> <chr> <dbl> <fct> <dbl>
1 2451… 12.2 24510 39.3 -76.6 Mary… Balti… Balt… 10.9 21251 461424
2 2451… 12.5 24510 39.3 -76.7 Mary… Balti… Balt… 10.9 21215 17645223
3 2451… 12.8 24510 39.3 -76.5 Mary… Balti… Balt… 10.9 21224 24539976
4 2451… 14.3 24510 39.2 -76.6 Mary… Balti… Balt… 10.9 21226 25718732
5 2451… 13.3 24510 39.3 -76.6 Mary… Balti… Balt… 10.9 21202 4111039
# … with 39 more variables: zcta_pop <dbl>, imp_a500 <dbl>, imp_a1000 <dbl>,
# imp_a5000 <dbl>, imp_a10000 <dbl>, imp_a15000 <dbl>, county_area <dbl>,
# county_pop <dbl>, log_dist_to_prisec <dbl>, log_pri_length_5000 <dbl>,
# log_pri_length_10000 <dbl>, log_pri_length_15000 <dbl>,
# log_pri_length_25000 <dbl>, log_prisec_length_500 <dbl>,
# log_prisec_length_1000 <dbl>, log_prisec_length_5000 <dbl>,
# log_prisec_length_10000 <dbl>, log_prisec_length_15000 <dbl>,
# log_prisec_length_25000 <dbl>, log_nei_2008_pm25_sum_10000 <dbl>,
# log_nei_2008_pm25_sum_15000 <dbl>, log_nei_2008_pm25_sum_25000 <dbl>,
# log_nei_2008_pm10_sum_10000 <dbl>, log_nei_2008_pm10_sum_15000 <dbl>,
# log_nei_2008_pm10_sum_25000 <dbl>, popdens_county <dbl>,
# popdens_zcta <dbl>, nohs <dbl>, somehs <dbl>, hs <dbl>, somecollege <dbl>,
# associate <dbl>, bachelor <dbl>, grad <dbl>, pov <dbl>, hs_orless <dbl>,
# urc2013 <dbl>, urc2006 <dbl>, aod <dbl>
There were in contrast five monitors for the city of Baltimore, despite the fact that if we take a look at the land area and population of the counties for Blatimore City and Albuquerque, we can see that they had very similar land area and populations.
# A tibble: 5 x 2
county_area county_pop
<dbl> <dbl>
1 209643241 620961
2 209643241 620961
3 209643241 620961
4 209643241 620961
5 209643241 620961
# A tibble: 2 x 2
county_area county_pop
<dbl> <dbl>
1 3006530549 662564
2 3006530549 662564
In fact, the county containing Albuerque had a larger population. Thus the measurements for Albuquerque were not as thorough as they were for Baltimore.
This may be due to the fact that the monitor values were lower in Albuquerque. It is interesting to note here that the CMAQ values are quite similar for both cities.
Evaluate correlation
In prediction analyses, it is also useful to evaluate if any of the variables are correlated. Why should we care about this?
If we are using a linear regression to model our data then we might run into a problem called multicolinearity which can lead us to misinterpret what is really predictive of our outcome variable. This phenomenon occurs when the predictor variables actually predict one another. See this case study for a deeper explanation about this.
Another reason we should look out for correlation is that we don’t want to include redundant variables. This can add unnecessary noise to our algorithm causing a reduction in prediction accuracy and it can cause our algorithm to be unnecessarily slower. Finally, it can also make it difficult to interpret what variables are actually predictive.
Intuitively we can expect some of our variables to be correlated.
Let’s first take a look at all of our numeric variables with thecorrplot package: The corrplot package is another option to look at correlation among possible predictors, and particularly useful if we have many predictors.
First, we calculate the Pearson correlation coefficients between all features pairwise using the cor() function of the stats package (which is loaded automatically). Then we use the corrplot::corrplot() function.
The tl.cex = 0.5 argument controls the size of the text label.
We can also plot the absolute value of the Pearson correlation coefficients using the abs() function from base R and change the order of the columns.

There are several options for ordering the variables. See here for more options. Here we will use the “hclust” option for ordering by hierarchical clustering - which will order the variables by how similar they are to one another.
The cl.lim = c(0, 1) argument limits the color label to be between 0 and 1.
We can see that the development variables (imp) variables are correlated with each other as we might expect. We also see that the road density variables seem to be correlated with each other, and the emission variables seem to be correlated with each other.
Also notice that none of the predictors are highly correlated with our outcome variable (value).
We can take also take a closer look using the ggcorr() function and the ggpairs() function of the GGally package.
To select our variables of interest we can use the select() function with the contains() function of the tidyr package.
First let’s look at the imp/development variables. We can change the default color palette (palette = "RdBu") and add on correlation coefficients to the plot (label = TRUE).


Indeed, we can see that imp_a1000 and imp_a500 are highly correlated, as well as imp_a10000, imp_a15000.
Next, let’s take a look at the road density data:

We can see that many of the road density variables are highly correlated with one another, while others are less so.
Finally let’s look at the emission variables.


We would also expect the population density data might correlate with some of these variables. Let’s take a look.


Interesting, so these variables don’t appear to be highly correlated, therefore we might need variables from each of the categories to predict our monitor PM2.5 pollution values.
Because some variables in our data have extreme values, it might be good to take a log transformation. This can affect our estimates of correlation.


Indeed this increased the correlation, but variables from each of these categories may still prove to be useful for prediction.
Now that we have a sense of what our data are, we can get started with building a machine learning model to predict air pollution.
Data Visualization
Our main question for this case study was:
Can we predict annual average air pollution concentrations at the granularity of zip code regional levels using predictors such as data about population density, urbanization, road density, as well as, satellite pollution data and chemical modeling data?
Thus far, we have build a machine learning (ML) model to predict fine particulate matter air pollution levels based on our predictor variables (or features).
Now, let’s make a plot of our predicted outcome values (\(\hat{Y}\)) and actual outcome values \(Y\) we observed.
First, let’s start by making a plot of our monitors. To do this, we will use the following packages to create a map of the US:
sf - the simple features package helps to convert geographical coordinates into geometry variables which are useful for making 2D plots
maps - this package contains geographical outlines and plotting functions to create plots with maps
rnaturalearth- this allows for easy interaction with map data from Natural Earth which is a public domain map dataset
rgeos - this package interfaces with the Geometry Engine-Open Source (GEOS) which is also helpful for coordinate conversion
We will start with getting an outline of the US with the ne_countries() function of the rnaturalearth package which will return polygons of the countries in the Natural Earth dataset.
Rows: 241
Columns: 64
$ scalerank <int> 3, 1, 1, 1, 1, 3, 3, 1, 1, 1, 3, 1, 5, 3, 1, 1, 1, 1, 1, 1…
$ featurecla <chr> "Admin-0 country", "Admin-0 country", "Admin-0 country", "…
$ labelrank <dbl> 5, 3, 3, 6, 6, 6, 6, 4, 2, 6, 4, 4, 5, 6, 6, 2, 4, 5, 6, 2…
$ sovereignt <chr> "Netherlands", "Afghanistan", "Angola", "United Kingdom", …
$ sov_a3 <chr> "NL1", "AFG", "AGO", "GB1", "ALB", "FI1", "AND", "ARE", "A…
$ adm0_dif <dbl> 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0…
$ level <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
$ type <chr> "Country", "Sovereign country", "Sovereign country", "Depe…
$ admin <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ adm0_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ geou_dif <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ geounit <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ gu_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ su_dif <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ subunit <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ su_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ brk_diff <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ name <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ name_long <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ brk_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ brk_name <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ brk_group <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ abbrev <chr> "Aruba", "Afg.", "Ang.", "Ang.", "Alb.", "Aland", "And.", …
$ postal <chr> "AW", "AF", "AO", "AI", "AL", "AI", "AND", "AE", "AR", "AR…
$ formal_en <chr> "Aruba", "Islamic State of Afghanistan", "People's Republi…
$ formal_fr <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ note_adm0 <chr> "Neth.", NA, NA, "U.K.", NA, "Fin.", NA, NA, NA, NA, "U.S.…
$ note_brk <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "Multiple clai…
$ name_sort <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania", "…
$ name_alt <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ mapcolor7 <dbl> 4, 5, 3, 6, 1, 4, 1, 2, 3, 3, 4, 4, 1, 7, 2, 1, 3, 1, 2, 3…
$ mapcolor8 <dbl> 2, 6, 2, 6, 4, 1, 4, 1, 1, 1, 5, 5, 2, 5, 2, 2, 1, 6, 2, 2…
$ mapcolor9 <dbl> 2, 8, 6, 6, 1, 4, 1, 3, 3, 2, 1, 1, 2, 9, 5, 2, 3, 5, 5, 1…
$ mapcolor13 <dbl> 9, 7, 1, 3, 6, 6, 8, 3, 13, 10, 1, NA, 7, 11, 5, 7, 4, 8, …
$ pop_est <dbl> 103065, 28400000, 12799293, 14436, 3639453, 27153, 83888, …
$ gdp_md_est <dbl> 2258.0, 22270.0, 110300.0, 108.9, 21810.0, 1563.0, 3660.0,…
$ pop_year <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ lastcensus <dbl> 2010, 1979, 1970, NA, 2001, NA, 1989, 2010, 2010, 2001, 20…
$ gdp_year <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ economy <chr> "6. Developing region", "7. Least developed region", "7. L…
$ income_grp <chr> "2. High income: nonOECD", "5. Low income", "3. Upper midd…
$ wikipedia <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ fips_10 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ iso_a2 <chr> "AW", "AF", "AO", "AI", "AL", "AX", "AD", "AE", "AR", "AM"…
$ iso_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALA", "AND", "ARE", "A…
$ iso_n3 <chr> "533", "004", "024", "660", "008", "248", "020", "784", "0…
$ un_a3 <chr> "533", "004", "024", "660", "008", "248", "020", "784", "0…
$ wb_a2 <chr> "AW", "AF", "AO", NA, "AL", NA, "AD", "AE", "AR", "AM", "A…
$ wb_a3 <chr> "ABW", "AFG", "AGO", NA, "ALB", NA, "ADO", "ARE", "ARG", "…
$ woe_id <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ adm0_a3_is <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALA", "AND", "ARE", "A…
$ adm0_a3_us <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", "A…
$ adm0_a3_un <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ adm0_a3_wb <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ continent <chr> "North America", "Asia", "Africa", "North America", "Europ…
$ region_un <chr> "Americas", "Asia", "Africa", "Americas", "Europe", "Europ…
$ subregion <chr> "Caribbean", "Southern Asia", "Middle Africa", "Caribbean"…
$ region_wb <chr> "Latin America & Caribbean", "South Asia", "Sub-Saharan Af…
$ name_len <dbl> 5, 11, 6, 8, 7, 5, 7, 20, 9, 7, 14, 10, 23, 22, 17, 9, 7, …
$ long_len <dbl> 5, 11, 6, 8, 7, 13, 7, 20, 9, 7, 14, 10, 27, 35, 19, 9, 7,…
$ abbrev_len <dbl> 5, 4, 4, 4, 4, 5, 4, 6, 4, 4, 9, 4, 7, 10, 6, 4, 5, 4, 4, …
$ tiny <dbl> 4, NA, NA, NA, NA, 5, 5, NA, NA, NA, 3, NA, NA, 2, 4, NA, …
$ homepart <dbl> NA, 1, 1, NA, 1, NA, 1, 1, 1, 1, NA, 1, NA, NA, 1, 1, 1, 1…
$ geometry <MULTIPOLYGON [°]> MULTIPOLYGON (((-69.89912 1..., MULTIPOLYGON …
Here you can see the data about the countries in the world. Notice the geometry variable. This is used to create the outlines that we want.
Now we can use the geom_sf() function of the ggplot2 package to create a visual of simple feature (the geometry coordinates found in the geometry variable).

So now we can see that we have outlines of all the countries in the world.
We want to limit this just to the coordinates for the US. We will do this based on the coordinates we found on Wikipedia. According to this link, these are the latitude and longitude bounds of the continental US:
- top = 49.3457868 # north lat
- left = -124.7844079 # west long
- right = -66.9513812 # east long
- bottom = 24.7433195 # south lat
Now we just have a plot that is mostly limited to the outline of the US.
Now we will use the geom_point() function of the ggplot package to add scatter plot on top of the map. We want to show where the monitors are located based on the latitude and longitude values in the data.
Nice!
Now let’s add county lines.
County graphical data is available from the maps package. The sf package which again is short for simple features creates a data frame about this graphical data so that we can work with it.
Simple feature collection with 3076 features and 1 field
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -124.6813 ymin: 25.12993 xmax: -67.00742 ymax: 49.38323
CRS: EPSG:4326
First 10 features:
ID geom
1 alabama,autauga MULTIPOLYGON (((-86.50517 3...
2 alabama,baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama,barbour MULTIPOLYGON (((-85.42801 3...
4 alabama,bibb MULTIPOLYGON (((-87.02083 3...
5 alabama,blount MULTIPOLYGON (((-86.9578 33...
6 alabama,bullock MULTIPOLYGON (((-85.66866 3...
7 alabama,butler MULTIPOLYGON (((-86.8604 31...
8 alabama,calhoun MULTIPOLYGON (((-85.74313 3...
9 alabama,chambers MULTIPOLYGON (((-85.59416 3...
10 alabama,cherokee MULTIPOLYGON (((-85.46812 3...
Now we will use this data within the geom_sf() function to add this to our plot. We will also add a title using the ggtitle() function, as well as remove axis ticks and titles using the theme() function of the ggplot2 package.
monitors <- ggplot(data = world) +
geom_sf(data = counties, fill = NA, color = gray(.5))+
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE) +
geom_point(data = pm, aes(x = lon, y = lat), size = 2,
shape = 23, fill = "darkred") +
ggtitle("Monitor Locations") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
monitors

Great!
Now, let’s add a fill at the county-level for the true monitor values of air pollution.
First, we need to get the county map data that we just got and our air pollution data to have similarly formatted county names so that we can combine the datasets together.
We can see that in the county data the counties are listed after the state name and a comma. In addition they are all lower case.
Simple feature collection with 6 features and 1 field
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -88.01778 ymin: 30.24071 xmax: -85.06131 ymax: 34.2686
CRS: EPSG:4326
ID geom
1 alabama,autauga MULTIPOLYGON (((-86.50517 3...
2 alabama,baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama,barbour MULTIPOLYGON (((-85.42801 3...
4 alabama,bibb MULTIPOLYGON (((-87.02083 3...
5 alabama,blount MULTIPOLYGON (((-86.9578 33...
6 alabama,bullock MULTIPOLYGON (((-85.66866 3...
In contrast, our air pollution pm data shows counties as titles with the first letter as upper case.
[1] "Baldwin" "Clay" "Colbert" "DeKalb" "Etowah" "Houston"
We can use the separate() function of the tidyr package to separate the ID variable of our counties data into two variables based on the comma as a separator.
Simple feature collection with 6 features and 2 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -88.01778 ymin: 30.24071 xmax: -85.06131 ymax: 34.2686
CRS: EPSG:4326
state county geom
1 alabama autauga MULTIPOLYGON (((-86.50517 3...
2 alabama baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama barbour MULTIPOLYGON (((-85.42801 3...
4 alabama bibb MULTIPOLYGON (((-87.02083 3...
5 alabama blount MULTIPOLYGON (((-86.9578 33...
6 alabama bullock MULTIPOLYGON (((-85.66866 3...
Now we just need to make these names in the new county variable of the counties data to be in title format. We can use the str_to_title() function of the stringr package to do this.
Great! Now the county information is the same for the counties and pm data.
We can use the inner_join() function of the dplyr package to join the datasets together based on the county variables in each. This function will keep all rows that are in both datasets.
Rows: 3,926
Columns: 52
$ state.x <chr> "alabama", "alabama", "alabama", "alabama…
$ county <chr> "Baldwin", "Bibb", "Bibb", "Butler", "But…
$ id <fct> 1003.001, 13021.0007, 13021.0012, 39017.0…
$ value <dbl> 9.597647, 12.253134, 12.233673, 13.918079…
$ fips <fct> 1003, 13021, 13021, 39017, 39017, 13059, …
$ lat <dbl> 30.49800, 32.77746, 32.80541, 39.49380, 3…
$ lon <dbl> -87.88141, -83.64110, -83.54352, -84.3543…
$ state.y <chr> "Alabama", "Georgia", "Georgia", "Ohio", …
$ city <chr> "In a city", "In a city", "In a city", "I…
$ CMAQ <dbl> 8.098836, 11.716801, 11.716801, 11.321991…
$ zcta <fct> 36532, 31206, 31020, 45044, 45015, 30605,…
$ zcta_area <dbl> 190980522, 72325015, 276913325, 98746815,…
$ zcta_pop <dbl> 27829, 29072, 2541, 52822, 12038, 39952, …
$ imp_a500 <dbl> 0.01730104, 35.64359862, 0.28200692, 27.4…
$ imp_a1000 <dbl> 1.4096021, 24.4824827, 0.2973616, 28.2887…
$ imp_a5000 <dbl> 3.3360118, 8.7317283, 2.4691097, 22.69740…
$ imp_a10000 <dbl> 1.9879187, 9.1999720, 1.9873487, 11.90155…
$ imp_a15000 <dbl> 1.4386207, 6.4619966, 3.6435089, 8.405292…
$ county_area <dbl> 4117521611, 646879637, 646879637, 1209668…
$ county_pop <dbl> 182265, 155547, 155547, 368130, 368130, 1…
$ log_dist_to_prisec <dbl> 4.648181, 7.635438, 7.576493, 5.959728, 5…
$ log_pri_length_5000 <dbl> 8.517193, 10.215058, 10.659655, 9.747731,…
$ log_pri_length_10000 <dbl> 9.210340, 12.116408, 11.653566, 10.734382…
$ log_pri_length_15000 <dbl> 9.630228, 12.591833, 12.313347, 11.172817…
$ log_pri_length_25000 <dbl> 11.32735, 13.12475, 13.02383, 12.14238, 1…
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 6.214608, 8.104926, 7…
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 7.600902, 9.180109, 8…
$ log_prisec_length_5000 <dbl> 10.81504, 11.61283, 11.34202, 11.63677, 1…
$ log_prisec_length_10000 <dbl> 11.88680, 13.23991, 12.47152, 12.62117, 1…
$ log_prisec_length_15000 <dbl> 12.20572, 13.74532, 13.37704, 13.26170, 1…
$ log_prisec_length_25000 <dbl> 13.41395, 14.28483, 14.25295, 14.16745, 1…
$ log_nei_2008_pm25_sum_10000 <dbl> 0.3180354, 5.5380414, 0.1972941, 7.230784…
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967359, 5.538041, 5.536822, 7.408732, 5…
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 5.986616, 5.986572, 7.538614, 7…
$ log_nei_2008_pm10_sum_10000 <dbl> 1.3558851, 5.6035407, 0.9849611, 7.278576…
$ log_nei_2008_pm10_sum_15000 <dbl> 2.2678341, 5.6035407, 5.5971561, 7.489928…
$ log_nei_2008_pm10_sum_25000 <dbl> 5.6287284, 6.0302900, 6.0347672, 7.633004…
$ popdens_county <dbl> 44.265706, 240.457407, 240.457407, 304.32…
$ popdens_zcta <dbl> 145.716431, 401.963277, 9.176156, 534.923…
$ nohs <dbl> 3.300, 8.700, 6.800, 1.300, 3.500, 3.800,…
$ somehs <dbl> 4.900, 24.700, 17.500, 3.300, 7.700, 6.80…
$ hs <dbl> 25.10, 32.60, 46.60, 33.40, 33.40, 17.80,…
$ somecollege <dbl> 19.7, 12.9, 18.7, 23.0, 23.2, 16.1, 18.8,…
$ associate <dbl> 8.200, 4.800, 5.000, 8.700, 8.100, 5.100,…
$ bachelor <dbl> 25.30, 8.90, 4.00, 22.20, 16.20, 25.40, 5…
$ grad <dbl> 13.50, 7.30, 1.30, 8.10, 7.90, 25.00, 3.1…
$ pov <dbl> 6.100, 38.800, 26.800, 0.900, 6.900, 12.1…
$ hs_orless <dbl> 33.30, 66.00, 70.90, 38.00, 44.60, 28.40,…
$ urc2013 <dbl> 4, 4, 4, 2, 2, 4, 6, 2, 4, 1, 1, 1, 3, 4,…
$ urc2006 <dbl> 5, 4, 4, 2, 2, 4, 6, 2, 4, 1, 1, 1, 3, 4,…
$ aod <dbl> 37.36364, 36.25000, 30.45455, 48.36364, 5…
$ geom <MULTIPOLYGON [°]> MULTIPOLYGON (((-87.93757 3.…
Nice! we can see that we have add a geom variable to the pm data.
Now we can use this to color the counties in our plot based on the value variable of our pm data, which you may recall is the actual monitor data for fine particulate air pollution at each monitor.
WE can do so using the scale_fill_gradientn() function of the ggplot2 package which creates color gradient based on a variable. In this case it is the variable that was specified as the fill in the aes function of the geom_sf() function. We specified that it would be the value variable of the pm data.
This scale_fill_gradientn() function also allows you to specify the colors, what to do about NA values (should they be a specific color or transparent) and the breaks, limits, labels and name/title on the legend for the color gradient.
truth <-ggplot(data = world) +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50), expand = FALSE)+
geom_sf(data = map_data, aes(fill = value)) +
scale_fill_gradientn(colours=topo.colors(7), na.value = "transparent",
breaks=c(0,10,20),labels=c(0,10,20),
limits=c(0,23.5), name = "PM ug/m3") +
ggtitle("True PM 2.5 levels") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
truth
Nice!
Now let’s do the same with our predicted outcome values.
Let’s grab both the testing and training predicted outcome values so that we have as much data as possible.
First we need to fit our training data with our final model to be able to get the predictions for the monitors included in the training set. We did this using the last_fit() function, but the output of this makes it difficult to grab the predicted values for the training data, and it is also difficult to get the id variables for the testing data.
Thus we will use the parsnip fit() and predict() functions of the parsnip package to do this like so:
Question Opportunity
Why do we not need pre-processed data?
Click here to reveal the answer.
Since we are using a workflow, the data will be pre-processed when it is fit as well.
# A tibble: 584 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 10.1 9.60 1003 Baldwin 1003.001
2 11.0 10.8 1027 Clay 1027.0001
3 11.4 11.2 1033 Colbert 1033.1002
4 12.0 12.4 1055 Etowah 1055.001
5 10.7 10.5 1069 Houston 1069.0003
6 14.4 15.6 1073 Jefferson 1073.0023
7 12.1 12.4 1073 Jefferson 1073.1005
8 11.0 11.1 1073 Jefferson 1073.1009
9 13.8 14.6 1073 Jefferson 1073.2003
10 11.8 12.0 1073 Jefferson 1073.5002
# … with 574 more rows
# A tibble: 292 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 11.7 11.7 1049 DeKalb 1049.1003
2 12.5 13.1 1073 Jefferson 1073.101
3 12.2 12.2 1073 Jefferson 1073.2006
4 12.0 12.2 1089 Madison 1089.0014
5 11.5 11.4 1103 Morgan 1103.0011
6 12.3 12.2 1121 Talladega 1121.0002
7 10.8 10.9 4013 Maricopa 4013.4003
8 10.6 10.6 4021 Pinal 4021.0001
9 12.1 14.1 4023 Santa Cruz 4023.0004
10 8.03 5.83 4025 Yavapai 4025.2002
# … with 282 more rows
Now we can combine this data for the predictions for all monitors using the bind_rows() function of the dplyr package, which will essentially append the second dataset to the first.
# A tibble: 876 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 11.7 11.7 1049 DeKalb 1049.1003
2 12.5 13.1 1073 Jefferson 1073.101
3 12.2 12.2 1073 Jefferson 1073.2006
4 12.0 12.2 1089 Madison 1089.0014
5 11.5 11.4 1103 Morgan 1103.0011
6 12.3 12.2 1121 Talladega 1121.0002
7 10.8 10.9 4013 Maricopa 4013.4003
8 10.6 10.6 4021 Pinal 4021.0001
9 12.1 14.1 4023 Santa Cruz 4023.0004
10 8.03 5.83 4025 Yavapai 4025.2002
# … with 866 more rows
Great! as we can see there are 876 values like we would expect for all of the monitors. We can use the county variable to combine this with the counties data like we did with the pm data previously so that we can use the value variable as a color scheme for our map.
map_data <- inner_join(counties, all_pred, by = "county")
pred <- ggplot(data = world) +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE) +
geom_sf(data = map_data, aes(fill = .pred)) +
scale_fill_gradientn(colours=topo.colors(7), na.value = "transparent",
breaks=c(0,10,20),labels=c(0,10,20),
limits=c(0,23.5), name = "PM ug/m3") +
ggtitle("Predicted PM 2.5 levels")+
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
pred

Now we will use the patchwork package to combine our last two plots. This allows us to combine plots using the + or the / . The + will place plots side by side and the / will place plots top to bottom.
Now let’s just combine the truth plot and the prediction plots together:

We can see that the predicted fine particle air pollution values in (ug/m3) are quite similar to the true values measured by the actual gravimetric monitors. We can also see that southern California has some large counties with worse pollution (as they are yellow and thus have much higher particulate matter levels).
Let’s add some text to our plot to explain it a bit more. We can do so using the plot_annotation() function of the patchwork package. The theme argument of this function takes the same theme information using the theme() function of the ggplot2 package as when creating ggplot2plots.

LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXM6IFByZWRpY3RpbmcgQW5udWFsIEFpciBQb2xsdXRpb24iCmNzczogc3R5bGUuY3NzCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgc2VsZl9jb250YWluZWQ6IHllcwogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vCiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogeWVzCgotLS0KPHN0eWxlPgojVE9DIHsKICBiYWNrZ3JvdW5kOiB1cmwoImh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pby9pbWcvbG9nby5qcGciKTsKICBiYWNrZ3JvdW5kLXNpemU6IGNvbnRhaW47CiAgcGFkZGluZy10b3A6IDI0MHB4ICFpbXBvcnRhbnQ7CiAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDsKfQo8L3N0eWxlPgoKPCEtLSBPcGVuIGFsbCBsaW5rcyBpbiBuZXcgdGFiLS0+ICAKPGJhc2UgdGFyZ2V0PSJfYmxhbmsiLz4gCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShrbml0cikKbGlicmFyeShoZXJlKQprbml0cjo6b3B0c19jaHVuayRzZXQoaW5jbHVkZSA9IFRSVUUsIGNvbW1lbnQgPSBOQSwgZWNobyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgY2FjaGUgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiLCBvdXQud2lkdGggPSAnOTAlJykKYGBgCgoKIyMjIyB7Lm91dGxpbmUgfQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiODAwIHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgIm1haW5fcGxvdF9tYXBzLnBuZyIpKQpgYGAKCiMjIyMKCiMjIyMgey5kaXNjbGFpbWVyX2Jsb2NrfQoKKipEaXNjbGFpbWVyKio6IFRoZSBwdXJwb3NlIG9mIHRoZSBbT3BlbiBDYXNlIFN0dWRpZXNdKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pbyl7dGFyZ2V0PSJfYmxhbmsifSBwcm9qZWN0IGlzICoqdG8gZGVtb25zdHJhdGUgdGhlIHVzZSBvZiB2YXJpb3VzIGRhdGEgc2NpZW5jZSBtZXRob2RzLCB0b29scywgYW5kIHNvZnR3YXJlIGluIHRoZSBjb250ZXh0IG9mIG1lc3N5LCByZWFsLXdvcmxkIGRhdGEqKi4gQSBnaXZlbiBjYXNlIHN0dWR5IGRvZXMgbm90IGNvdmVyIGFsbCBhc3BlY3RzIG9mIHRoZSByZXNlYXJjaCBwcm9jZXNzLCBpcyBub3QgY2xhaW1pbmcgdG8gYmUgdGhlIG1vc3QgYXBwcm9wcmlhdGUgd2F5IHRvIGFuYWx5emUgYSBnaXZlbiBkYXRhIHNldCwgYW5kIHNob3VsZCBub3QgYmUgdXNlZCBpbiB0aGUgY29udGV4dCBvZiBtYWtpbmcgcG9saWN5IGRlY2lzaW9ucyB3aXRob3V0IGV4dGVybmFsIGNvbnN1bHRhdGlvbiBmcm9tIHNjaWVudGlmaWMgZXhwZXJ0cy4gCgojIyMjCgojIyMjIHsubGljZW5zZV9ibG9ja30KClRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciB0aGUgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBbKENDIEJZLU5DIDMuMCldKGh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvdXMvKXt0YXJnZXQ9Il9ibGFuayJ9IFVuaXRlZCBTdGF0ZXMgTGljZW5zZS4KCiMjIyMKCiMjIyMgey5yZWZlcmVuY2VfYmxvY2t9CgpUbyBjaXRlIHRoaXMgY2FzZSBzdHVkeSBwbGVhc2UgdXNlOgoKV3JpZ2h0LCBDYXJyaWUgYW5kIEphZ2VyLCBMZWFoIGFuZCBUYXViLCBNYXJnYXJldCBhbmQgSGlja3MsIFN0ZXBoYW5pZS4gKDIwMjApLiBbaHR0cHM6Ly93d3cub3BlbmNhc2VzdHVkaWVzLm9yZy9vY3MtYnAtYWlyLXBvbGx1dGlvbi9dKGh0dHBzOi8vd3d3Lm9wZW5jYXNlc3R1ZGllcy5vcmcvb2NzLWJwLWFpci1wb2xsdXRpb24vKS4gUHJlZGljdGluZyBBbm51YWwgQWlyIFBvbGx1dGlvbiAoVmVyc2lvbiB2MS4wLjApLgoKIyMjIwoKIyAqKk1vdGl2YXRpb24qKgoqKioKQSB2YXJpZXR5IG9mIGRpZmZlcmVudCBzb3VyY2VzIGNvbnRyaWJ1dGUgZGlmZmVyZW50IHR5cGVzIG9mIHBvbGx1dGFudHMgdG8gd2hhdCB3ZSBjYWxsIGFpciBwb2xsdXRpb24uIAoKU29tZSBzb3VyY2VzIGFyZSBuYXR1cmFsIHdoaWxlIG90aGVycyBhcmUgYW50aHJvcG9nZW5pYyAoaHVtYW4gZGVyaXZlZCk6Cgo8cCBhbGlnbj0iY2VudGVyIj4KPGltZyB3aWR0aD0iNjAwIiBzcmM9Imh0dHBzOi8vd3d3Lm5wcy5nb3Yvc3ViamVjdHMvYWlyL2ltYWdlcy9Tb3VyY2VzX0dyYXBoaWNfSHVnZS5qcGc/bWF4d2lkdGg9MTIwMCZtYXhoZWlnaHQ9MTIwMCZhdXRvcm90YXRlPWZhbHNlIj4KPC9wPgoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5nb29nbGUuY29tL3VybD9zYT1pJnVybD1odHRwcyUzQSUyRiUyRnd3dy5ucHMuZ292JTJGc3ViamVjdHMlMkZhaXIlMkZzb3VyY2VzLmh0bSZwc2lnPUFPdlZhdzJ2N0FWeFNGOFpTQVBFaE51ZFZ0Yk4mdXN0PTE1ODU3NzA5NjYyMTcwMDAmc291cmNlPWltYWdlcyZjZD12ZmUmdmVkPTBDQUlRalJ4cUZ3b1RDUERONjZxX3hlZ0NGUUFBQUFBZEFBQUFBQkFEKXt0YXJnZXQ9Il9ibGFuayJ9CgojIyMgTWFqb3IgdHlwZXMgb2YgYWlyIHBvbGx1dGFudHMKCjEpICoqR2FzZW91cyoqIC0gQ2FyYm9uIE1vbm94aWRlIChDTyksIE96b25lIChPfjN+KSwgTml0cm9nZW4gT3hpZGVzKE5PLCBOT34yfiksIFN1bHBoZXIgRGlveGlkZSAoU09+Mn4pCjIpICoqUGFydGljdWxhdGUqKiAtIHNtYWxsIGxpcXVpZHMgYW5kIHNvbGlkcyBzdXNwZW5kZWQgaW4gdGhlIGFpciAoaW5jbHVkZXMgbGVhZC0gY2FuIGluY2x1ZGUgY2VydGFpbiB0eXBlcyBvZiBkdXN0KQozKSAqKkR1c3QqKiAtIHNtYWxsIHNvbGlkcyAobGFyZ2VyIHRoYW4gcGFydGljdWxhdGVzKSB0aGF0IGNhbiBiZSBzdXNwZW5kZWQgaW4gdGhlIGFpciBmb3Igc29tZSB0aW1lIGJ1dCBldmVudHVhbGx5IHNldHRsZQo0KSAqKkJpb2xvZ2ljYWwqKiAtIHBvbGxlbiwgYmFjdGVyaWEsIHZpcnVzZXMsIG1vbGQgc3BvcmVzCgpTZWUgW2hlcmVdKGh0dHA6Ly93d3cucmVkbG9nZW52LmNvbS93b3JrZXItc2FmZXR5L3BhcnQtMS1kdXN0LWFuZC1wYXJ0aWN1bGF0ZS1tYXR0ZXIpIGZvciBtb3JlIGRldGFpbCBvbiB0aGUgdHlwZXMgb2YgcG9sbHV0YW50cyBpbiB0aGUgYWlyLgoKCiMjIyBQYXJ0aWN1bGF0ZSBwb2xsdXRpb24gCgpBaXIgcG9sbHV0aW9uIHBhcnRpY3VsYXRlcyBhcmUgZ2VuZXJhbGx5IGRlc2NyaWJlZCBieSB0aGVpciAqKnNpemUqKi4KClRoZXJlIGFyZSAzIG1ham9yIGNhdGVnb3JpZXM6CgoxKSAqKkxhcmdlIENvYXJzZSoqIFBhcnRpY3VsYXRlIE1hdHRlciAtIGhhcyBkaWFtZXRlciBvZiA+MTAgbWljcm9tZXRlcnMgKDEwIMK1bSkgCgoyKSAqKkNvYXJzZSoqIFBhcnRpY3VsYXRlIE1hdHRlciAoY2FsbGVkICoqUE1+MTAtMi41fioqKSAtIGhhcyBkaWFtZXRlciBvZiBiZXR3ZWVuIDIuNSDCtW0gYW5kIDEwIMK1bQoKMykgKipGaW5lKiogUGFydGljdWxhdGUgTWF0dGVyIChjYWxsZWQgKipQTX4yLjV+KiopIC0gaGFzIGRpYW1ldGVyIG9mIDwgMi41IMK1bSAKCioqUE1+MTB+KiogaW5jbHVkZXMgYW55IHBhcnRpY3VsYXRlIG1hdHRlciA8MTAgwrVtIChib3RoIGNvYXJzZSBhbmQgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIpCgpIZXJlIHlvdSBjYW4gc2VlIGhvdyB0aGVzZSBzaXplcyBjb21wYXJlIHdpdGggYSBodW1hbiBoYWlyOgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSAiNjAwIHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInBtMi41X3NjYWxlX2dyYXBoaWMtY29sb3JfMi5qcGciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmVwYS5nb3YvcG0tcG9sbHV0aW9uL3BhcnRpY3VsYXRlLW1hdHRlci1wbS1iYXNpY3Mpe3RhcmdldD0iX2JsYW5rIn0KCjwhLS0gPHAgYWxpZ249ImNlbnRlciI+IC0tPgo8IS0tICAgPGltZyB3aWR0aD0iNTAwIiBzcmM9Imh0dHBzOi8vd3d3LnNlbnNpcmlvbi5jb20vaW1hZ2VzL3NlbnNpcmlvbi1zcGVjaWFsaXN0LWFydGljbGUtZmlndXJlLTEtY2RkNzAuanBnIj4gLS0+CjwhLS0gPC9wPiAtLT4KCgo8dT5UaGUgZm9sbG93aW5nIHBsb3QgYW5kIHRhYmxlIHNob3cgdGhlIHJlbGF0aXZlIHNpemVzIG9mIHRoZXNlIGRpZmZlcmVudCBwb2xsdXRhbnRzIGluIG1pY3JvbWV0ZXJzICjCtW0pOjwvdT4KCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0gIjgwMCBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJwYXJ0aWN1bGF0ZS1zaXplLWNoYXJ0LnBuZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUGFydGljdWxhdGVzKXt0YXJnZXQ9Il9ibGFuayJ9CgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSAiODAwIHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInBhcnRpY3VsYXRlX3R5cGVzLmpwZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuZnJvbnRpZXJzaW4ub3JnL2FydGljbGVzLzEwLjMzODkvZnB1YmguMjAyMC4wMDAxNC9mdWxsKXt0YXJnZXQ9Il9ibGFuayJ9CgoKPHU+VGhpcyB0YWJsZSBzaG93cyBob3cgZGVlcGx5IHNvbWUgb2YgdGhlIHNtYWxsZXIgZmluZSBwYXJ0aWNsZXMgY2FuIHBlbmV0cmF0ZSB3aXRoaW4gdGhlIGh1bWFuIGJvZHk6PC91PgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSAiODAwIHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInNpemVzLmpwZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuZnJvbnRpZXJzaW4ub3JnL2FydGljbGVzLzEwLjMzODkvZnB1YmguMjAyMC4wMDAxNC9mdWxsKXt0YXJnZXQ9Il9ibGFuayJ9CgoKIyMjIE5lZ2F0aXZlIGltcGFjdCBvZiBwYXJ0aWN1bGF0ZSBleHBvc3VyZSBvbiBoZWFsdGggCgpFeHBvc3VyZSB0byBhaXIgcG9sbHV0aW9uIGlzIGFzc29jaWF0ZWQgd2l0aCBoaWdoZXIgcmF0ZXMgb2YgW21vcnRhbGl0eV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DNTc4MzE4Ni8pe3RhcmdldD0iX2JsYW5rIn0gaW4gb2xkZXIgYWR1bHRzIGFuZCBpcyBrbm93biB0byBiZSBhIHJpc2sgZmFjdG9yIGZvciBtYW55IGRpc2Vhc2VzIGFuZCBjb25kaXRpb25zIGluY2x1ZGluZyBidXQgbm90IGxpbWl0ZWQgdG86CgoxKSBbQXN0aG1hXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8yOTI0MzkzNyl7dGFyZ2V0PSJfYmxhbmsifSAtIGZpbmUgcGFydGljbGUgZXhwb3N1cmUgKCoqUE1+Mi41fioqKSB3YXMgZm91bmQgdG8gYmUgYXNzb2NpYXRlZCB3aXRoIGhpZ2hlciByYXRlcyBvZiBhc3RobWEgaW4gY2hpbGRyZW4KMikgW0luZmxhbW1hdGlvbiBpbiB0eXBlIDEgZGlhYmV0ZXNdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHVibWVkLzMxNDE5NzY1KXt0YXJnZXQ9Il9ibGFuayJ9IC0gZmluZSBwYXJ0aWNsZSBleHBvc3VyZSAoKipQTX4yLjV+KiopIGZyb20gdHJhZmZpYy1yZWxhdGVkIGFpciBwb2xsdXRpb24gd2FzIGFzc29jaWF0ZWQgd2l0aCBpbmNyZWFzZWQgbWVhc3VyZXMgb2YgaW5mbGFtbWF0b3J5IG1hcmtlcnMgaW4geW91dGhzIHdpdGggVHlwZSAxIGRpYWJldGVzCjMpIFtMdW5nIGZ1bmN0aW9uIGFuZCBlbXBoeXNlbWFdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcHVibWVkLzMxNDA4MTM1KXt0YXJnZXQ9Il9ibGFuayJ9IC0gaGlnaGVyIGNvbmNlbnRyYXRpb25zIG9mIG96b25lIChPfjN+KSwgbml0cm9nZW4gb3hpZGVzIChOT354fiksIGJsYWNrIGNhcmJvbiwgYW5kIGZpbmUgcGFydGljbGUgZXhwb3N1cmUgKipQTX4yLjV+KiogLCBhdCBzdHVkeSBiYXNlbGluZSB3ZXJlIHNpZ25pZmljYW50bHkgYXNzb2NpYXRlZCB3aXRoIGdyZWF0ZXIgaW5jcmVhc2VzIGluIHBlcmNlbnQgZW1waHlzZW1hIHBlciAxMCB5ZWFycyAKNCkgW0xvdyBiaXJ0aHdlaWdodF0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMzEzODY2NDMpe3RhcmdldD0iX2JsYW5rIn0gLSBmaW5lIHBhcnRpY2xlIGV4cG9zdXJlKCoqUE1+Mi41fioqKSB3YXMgYXNzb2NpYXRlZCB3aXRoIGxvd2VyIGJpcnRoIHdlaWdodCBpbiBmdWxsLXRlcm0gbGl2ZSBiaXJ0aHMKNSkgW1ZpcmFsIEluZmVjdGlvbl0oaHR0cHM6Ly93d3cudGFuZGZvbmxpbmUuY29tL2RvaS9mdWxsLzEwLjEwODAvMDg5NTgzNzA3MDE2NjU0MzQpe3RhcmdldD0iX2JsYW5rIn0gLSBoaWdoZXIgcmF0ZXMgb2YgaW5mZWN0aW9uIGFuZCBpbmNyZWFzZWQgc2V2ZXJpdHkgb2YgaW5mZWN0aW9uIGFyZSBhc3NvY2lhdGVkIHdpdGggaGlnaGVyIGV4cG9zdXJlcyB0byBwb2xsdXRpb24gbGV2ZWxzIGluY2x1ZGluZyBmaW5lIHBhcnRpY2xlIGV4cG9zdXJlICgqKlBNfjIuNX4qKikKClNlZSB0aGlzIFtyZXZpZXcgYXJ0aWNsZV0oaHR0cHM6Ly93d3cuZnJvbnRpZXJzaW4ub3JnL2FydGljbGVzLzEwLjMzODkvZnB1YmguMjAyMC4wMDAxNC9mdWxsKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IHNvdXJjZXMgb2YgYWlyIHBvbGx1dGlvbiBhbmQgdGhlIGluZmx1ZW5jZSBvZiBhaXIgcG9sbHV0aW9uIG9uIGhlYWx0aC4KCiMjIyBTcGFyc2UgbW9uaXRvcmluZyBpcyBwcm9ibGVtYXRpYyBmb3IgUHVibGljIEhlYWx0aAoKSGlzdG9yaWNhbGx5LCBlcGlkZW1pb2xvZ2ljYWwgc3R1ZGllcyB3b3VsZCBhc3Nlc3MgdGhlIGluZmx1ZW5jZSBvZiBhaXIgcG9sbHV0aW9uIG9uIGhlYWx0aCBvdXRjb21lcyBieSByZWx5aW5nIG9uIGEgbnVtYmVyIG9mIG1vbml0b3JzIGxvY2F0ZWQgYXJvdW5kIHRoZSBjb3VudHJ5LiAKCkhvd2V2ZXIsIGFzIGNhbiBiZSBzZWVuIGluIHRoZSBmb2xsb3dpbmcgZmlndXJlLCB0aGVzZSBtb25pdG9ycyBhcmUgcmVsYXRpdmVseSBzcGFyc2UgaW4gY2VydGFpbiByZWdpb25zIG9mIHRoZSBjb3VudHJ5IGFuZCBhcmUgbm90IG5lY2Vzc2FyaWx5IGxvY2F0ZWQgbmVhciBwb2xsdXRpb24gc291cmNlcy4gV2Ugd2lsbCBzZWUgbGF0ZXIgd2hlbiB3ZSBldmFsdWF0ZSB0aGUgZGF0YSwgdGhhdCBldmVuIGluIGNlcnRhaW4gcmVsYXRpdmVseSBsYXJnZSBjaXRpZXMgdGhlcmUgaXMgb25seSAgb25lIG1vbml0b3IhCgpGdXJ0aGVybW9yZSwgZHJhbWF0aWMgZGlmZmVyZW5jZXMgaW4gcG9sbHV0aW9uIHJhdGVzIGNhbiBiZSBzZWVuIGV2ZW4gd2l0aGluIHRoZSBzYW1lIGNpdHkuIEluIGZhY3QsIHRoZSB0ZXJtIG1pY3JvLWVudmlyb25tZW50cyBkZXNjcmliZXMgZW52aXJvbm1lbnQgd2l0aGluIGNpdGllcyBvciBjb3VudGllcyB3aGljaCBtYXkgdmFyeSBncmVhdGx5IGZyb20gb25lIGJsb2NrIHRvIGFub3RoZXIuCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9ICI4MDAgcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAibWFwX29mX21vbml0b3JzLmpwZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9laGpvdXJuYWwuYmlvbWVkY2VudHJhbC5jb20vYXJ0aWNsZXMvMTAuMTE4Ni8xNDc2LTA2OVgtMTMtNjMpe3RhcmdldD0iX2JsYW5rIn0KClRoaXMgbGFjayBvZiBncmFudWxhcml0eSBpbiBhaXIgcG9sbHV0aW9uIG1vbml0b3JpbmcgaGFzIGhpbmRlcmVkIG91ciBhYmlsaXR5IHRvIGRpc2Nlcm4gdGhlIGZ1bGwgaW1wYWN0IG9mIGFpciBwb2xsdXRpb24gb24gaGVhbHRoIGFuZCB0byBpZGVudGlmeSBhdC1yaXNrIGxvY2F0aW9ucy4gCgoKIyMjIE1hY2hpbmUgbGVhcm5pbmcgb2ZmZXJzIGEgc29sdXRpb24KCkFuIFthcnRpY2xlXShodHRwczovL2Voam91cm5hbC5iaW9tZWRjZW50cmFsLmNvbS9hcnRpY2xlcy8xMC4xMTg2LzE0NzYtMDY5WC0xMy02Myl7dGFyZ2V0PSJfYmxhbmsifSBwdWJsaXNoZWQgaW4gdGhlICpFbnZpcm9ubWVudGFsIEhlYWx0aCogam91cm5hbCBkZWFsdCB3aXRoIHRoaXMgaXNzdWUgYnkgdXNpbmcgZGF0YSwgaW5jbHVkaW5nIHBvcHVsYXRpb24gZGVuc2l0eSwgcm9hZCBkZW5zaXR5LCBhbW9uZyBvdGhlciBmZWF0dXJlcywgdG8gbW9kZWwgb3IgcHJlZGljdCBhaXIgcG9sbHV0aW9uIGxldmVscyBhdCBhIG1vcmUgbG9jYWxpemVkIHNjYWxlIHVzaW5nIG1hY2hpbmUgbGVhcm5pbmcgKE1MKSBtZXRob2RzLiAKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0gIjgwMCBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJ0aGVwYXBlci5wbmciKSkKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vZWhqb3VybmFsLmJpb21lZGNlbnRyYWwuY29tL2FydGljbGVzLzEwLjExODYvMTQ3Ni0wNjlYLTEzLTYzKXt0YXJnZXQ9Il9ibGFuayJ9CgojIyMjIHsucmVmZXJlbmNlX2Jsb2NrfQpZYW5vc2t5LCBKLiBELiBldCBhbC4gU3BhdGlvLXRlbXBvcmFsIG1vZGVsaW5nIG9mIHBhcnRpY3VsYXRlIGFpciBwb2xsdXRpb24gaW4gdGhlIGNvbnRlcm1pbm91cyBVbml0ZWQgU3RhdGVzIHVzaW5nIGdlb2dyYXBoaWMgYW5kIG1ldGVvcm9sb2dpY2FsIHByZWRpY3RvcnMuICpFbnZpcm9uIEhlYWx0aCogMTMsIDYzICgyMDE0KS4KCiMjIyMKClRoZSBhdXRob3JzIG9mIHRoaXMgYXJ0aWNsZSBzdGF0ZSB0aGF0OgoKPiAiRXhwb3N1cmUgdG8gYXRtb3NwaGVyaWMgcGFydGljdWxhdGUgbWF0dGVyIChQTSkgcmVtYWlucyBhbiBpbXBvcnRhbnQgcHVibGljIGhlYWx0aCBjb25jZXJuLCBhbHRob3VnaCBpdCByZW1haW5zIGRpZmZpY3VsdCB0byBxdWFudGlmeSBhY2N1cmF0ZWx5IGFjcm9zcyBsYXJnZSBnZW9ncmFwaGljIGFyZWFzIHdpdGggc3VmZmljaWVudGx5IGhpZ2ggc3BhdGlhbCByZXNvbHV0aW9uLiBSZWNlbnQgZXBpZGVtaW9sb2dpYyBhbmFseXNlcyBoYXZlIGRlbW9uc3RyYXRlZCB0aGUgaW1wb3J0YW5jZSBvZiBzcGF0aWFsbHktIGFuZCB0ZW1wb3JhbGx5LXJlc29sdmVkIGV4cG9zdXJlIGVzdGltYXRlcywgd2hpY2ggc2hvdyBsYXJnZXIgUE0tbWVkaWF0ZWQgaGVhbHRoIGVmZmVjdHMgYXMgY29tcGFyZWQgdG8gbmVhcmVzdCBtb25pdG9yIG9yIGNvdW50eS1zcGVjaWZpYyBhbWJpZW50IGNvbmNlbnRyYXRpb25zLiIgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vZWhqb3VybmFsLmJpb21lZGNlbnRyYWwuY29tL2FydGljbGVzLzEwLjExODYvMTQ3Ni0wNjlYLTEzLTYzKXt0YXJnZXQ9Il9ibGFuayJ9CgpUaGUgYXJ0aWNsZSBhYm92ZSBkZW1vbnN0cmF0ZXMgdGhhdCBtYWNoaW5lIGxlYXJuaW5nIG1ldGhvZHMgY2FuIGJlIHVzZWQgdG8gcHJlZGljdCBhaXIgcG9sbHV0aW9uIGxldmVscyB3aGVuIHRyYWRpdGlvbmFsIG1vbml0b3Jpbmcgc3lzdGVtcyBhcmUgbm90IGF2YWlsYWJsZSBpbiBhIHBhcnRpY3VsYXIgYXJlYSBvciB3aGVuIHRoZXJlIGlzIG5vdCBlbm91Z2ggc3BhdGlhbCBncmFudWxhcml0eSB3aXRoIGN1cnJlbnQgbW9uaXRvcmluZyBzeXN0ZW1zLiAKV2Ugd2lsbCB1c2Ugc2ltaWxhciBtZXRob2RzIHRvIHByZWRpY3QgYW5udWFsIGFpciBwb2xsdXRpb24gbGV2ZWxzIHNwYXRpYWxseSB3aXRoaW4gdGhlIFVTLgoKCiMgKipNYWluIFF1ZXN0aW9uKioKKioqCgojIyMjIHsubWFpbl9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IE91ciBtYWluIHF1ZXN0aW9uOiA8L3U+PC9iPgoKMSkgQ2FuIHdlIHByZWRpY3QgYW5udWFsIGF2ZXJhZ2UgYWlyIHBvbGx1dGlvbiBjb25jZW50cmF0aW9ucyBhdCB0aGUgZ3JhbnVsYXJpdHkgb2YgemlwIGNvZGUgcmVnaW9uYWwgbGV2ZWxzIHVzaW5nIHByZWRpY3RvcnMgc3VjaCBhcyBkYXRhIGFib3V0IHBvcHVsYXRpb24gZGVuc2l0eSwgdXJiYW5pemF0aW9uLCByb2FkIGRlbnNpdHksIGFzIHdlbGwgYXMsIHNhdGVsbGl0ZSBwb2xsdXRpb24gZGF0YSBhbmQgY2hlbWljYWwgbW9kZWxpbmcgZGF0YT8KCiMjIyMKCiMgKipMZWFybmluZyBPYmplY3RpdmVzKioKKioqCgpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIHdpbGwgd2FsayB5b3UgdGhyb3VnaCBpbXBvcnRpbmcgZGF0YSBmcm9tIENTViBmaWxlcyBhbmQgcGVyZm9ybWluZyBtYWNoaW5lIGxlYXJuaW5nIG1ldGhvZHMgdG8gcHJlZGljdCBvdXIgb3V0Y29tZSB2YXJpYWJsZSBvZiBpbnRlcmVzdCAoaW4gdGhpcyBjYXNlIGFubnVhbCBmaW5lIHBhcnRpY2xlIGFpciBwb2xsdXRpb24gZXN0aW1hdGVzKS4gCgpXZSB3aWxsIGVzcGVjaWFsbHkgZm9jdXMgb24gdXNpbmcgcGFja2FnZXMgYW5kIGZ1bmN0aW9ucyBmcm9tIHRoZSBbYHRpZHl2ZXJzZWBdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9LCBhbmQgbW9yZSBzcGVjaWZpY2FsbHkgdGhlIFtgdGlkeW1vZGVsc2BdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy90aWR5bW9kZWxzL3RpZHltb2RlbHMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHBhY2thZ2UvZWNvc3lzdGVtIHByaW1hcmlseSBkZXZlbG9wZWQgYW5kIG1haW50YWluZWQgYnkgW01heCBLdWhuXShodHRwczovL3Jlc291cmNlcy5yc3R1ZGlvLmNvbS9hdXRob3JzL21heC1rdWhuKXt0YXJnZXQ9Il9ibGFuayJ9IGFuZCBbRGF2aXMgVmF1Z2hhbl0oaHR0cHM6Ly9yZXNvdXJjZXMucnN0dWRpby5jb20vYXV0aG9ycy9kYXZpcy12YXVnaGFuKXt0YXJnZXQ9Il9ibGFuayJ9LiAKVGhpcyBwYWNrYWdlIGxvYWRzIG1vcmUgbW9kZWxpbmcgcmVsYXRlZCBwYWNrYWdlcyBsaWtlIGByc2FtcGxlYCwgYHJlY2lwZXNgLCBgcGFyc25pcGAsIGB5YXJkc3RpY2tgLCBgd29ya2Zsb3dzYCwgYW5kIGB0dW5lYCBwYWNrYWdlcy4gCgpUaGUgdGlkeXZlcnNlIGlzIGEgbGlicmFyeSBvZiBwYWNrYWdlcyBjcmVhdGVkIGJ5IFJTdHVkaW8uIApXaGlsZSBzb21lIHN0dWRlbnRzIG1heSBiZSBmYW1pbGlhciB3aXRoIHByZXZpb3VzIFIgcHJvZ3JhbW1pbmcgcGFja2FnZXMsIHRoZXNlIHBhY2thZ2VzIG1ha2UgZGF0YSBzY2llbmNlIGluIFIgZXNwZWNpYWxseSBsZWdpYmxlIGFuZCBpbnR1aXRpdmUuCgoKYGBge3IsIG91dC53aWR0aCA9ICIyMCUiLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciJ9CmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vdGlkeXZlcnNlLnRpZHl2ZXJzZS5vcmcvbG9nby5wbmciKQpgYGAKClRoZSBza2lsbHMsIG1ldGhvZHMsIGFuZCBjb25jZXB0cyB0aGF0IHN0dWRlbnRzIHdpbGwgYmUgZmFtaWxpYXIgd2l0aCBieSB0aGUgZW5kIG9mIHRoaXMgY2FzZSBzdHVkeSBhcmU6CgoKPHU+KipEYXRhIFNjaWVuY2UgTGVhcm5pbmcgT2JqZWN0aXZlczoqKjwvdT4gCiAgCjEuIEZhbWlsaWFyaXR5IHdpdGggdGhlIHRpZHltb2RlbHMgZWNvc3lzdGVtCjIuIEFiaWxpdHkgdG8gZXZhbHVhdGUgY29ycmVsYXRpb24gYW1vbmcgcHJlZGljdG9yIHZhcmlhYmxlcyAoYGNvcnJwbG90YCBhbmQgYEdHYWxseWApCjMuIEFiaWxpdHkgdG8gaW1wbGVtZW50IHRpZHltb2RlbHMgcGFja2FnZXMgc3VjaCBhcyBgcnNhbXBsZWAgdG8gc3BsaXQgdGhlIGRhdGEgaW50byB0cmFpbmluZyBhbmQgdGVzdGluZyBzZXRzIGFzIHdlbGwgYXMgY3Jvc3MgdmFsaWRhdGlvbiBzZXRzLgo0LiBBYmlsaXR5IHRvIHVzZSB0aGUgYHJlY2lwZXNgLCBgcGFyc25pcGAsIGFuZCBgd29ya2Zsb3dzYCB0byB0cmFpbiBhbmQgdGVzdCBhIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIGFuZCByYW5kb20gZm9yZXN0IG1vZGVsCjUuIERlbW9uc3RyYXRlIGhvdyB0byB2aXN1YWxpemUgZ2VvLXNwYXRpYWwgZGF0YSB1c2luZyBgZ2dwbG90MmAKCjx1PioqU3RhdGlzdGljYWwgTGVhcm5pbmcgT2JqZWN0aXZlczoqKjwvdT4gIAogIAoxLiBCYXNpYyB1bmRlcnN0YW5kaW5nIHRoZSB1dGlsaXR5IG9mIG1hY2hpbmUgbGVhcm5pbmcgZm9yIHByZWRpY3Rpb24gYW5kIGNsYXNzaWZpY2F0aW9uCjIuIFVuZGVyc3RhbmRpbmcgb2YgdGhlIG5lZWQgZm9yIHRyYWluaW5nIGFuZCB0ZXN0IHNldHMKMy4gVW5kZXJzdGFuZGluZyBvZiB0aGUgdXRpbGl0eSBvZiBjcm9zcyB2YWxpZGF0aW9uCjQuIFVuZGVyc3RhbmRpbmcgb2YgcmFuZG9tIGZvcmVzdAo1LiBIb3cgdG8gaW50ZXJwcmV0IHJvb3QgbWVhbiBzcXVhcmVkIGVycm9yIChybXNlKSB0byBhc3Nlc3MgcGVyZm9ybWFuY2UgZm9yIHByZWRpY3Rpb24KCgoKYGBge3IsIG91dC53aWR0aCA9ICIxMDBweCIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly9wYnMudHdpbWcuY29tL21lZGlhL0RrQkZwU3NXNEFJeXlJTi5wbmciKQpgYGAKCgpXZSB3aWxsIGJlZ2luIGJ5IGxvYWRpbmcgdGhlIHBhY2thZ2VzIHRoYXQgd2Ugd2lsbCBuZWVkOgoKYGBge3J9CmxpYnJhcnkoaGVyZSkKbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeShza2ltcikKbGlicmFyeShzdW1tYXJ5dG9vbHMpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoY29ycnBsb3QpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KEdHYWxseSkKbGlicmFyeSh0aWR5bW9kZWxzKQpsaWJyYXJ5KHdvcmtmbG93cykKbGlicmFyeSh2aXApCmxpYnJhcnkodHVuZSkKbGlicmFyeShyYW5kb21Gb3Jlc3QpCmxpYnJhcnkoZG9QYXJhbGxlbCkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkobHdnZW9tKQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KG1hcHMpCmxpYnJhcnkocm5hdHVyYWxlYXJ0aCkKbGlicmFyeShyZ2VvcykKbGlicmFyeShwYXRjaHdvcmspCmBgYAoKCiA8dT4qKlBhY2thZ2VzIHVzZWQgaW4gdGhpcyBjYXNlIHN0dWR5OioqIDwvdT4KClBhY2thZ2UgICB8IFVzZSBpbiB0aGlzIGNhc2Ugc3R1ZHkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCi0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS0KW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjL2hlcmVfaGVyZSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgICB8IHRvIGVhc2lseSBsb2FkIGFuZCBzYXZlIGRhdGEKW3JlYWRyXShodHRwczovL3JlYWRyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBpbXBvcnQgQ1NWIGZpbGVzCltkcGx5cl0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gdmlldy9hcnJhbmdlL2ZpbHRlci9zZWxlY3QvY29tcGFyZSBzcGVjaWZpYyBzdWJzZXRzIG9mIGRhdGEgCltza2ltcl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhCltzdW1tYXJ5dG9vbHNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9za2ltci9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBnZXQgYW4gb3ZlcnZpZXcgb2YgZGF0YSBpbiBhIGRpZmZlcmVudCBzdHlsZQpbbWFncml0dHJdKGh0dHBzOi8vbWFncml0dHIudGlkeXZlcnNlLm9yZy9hcnRpY2xlcy9tYWdyaXR0ci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byB1c2UgdGhlIGAlPD4lYCBwaXBwaW5nIG9wZXJhdG9yIApbY29ycnBsb3RdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9jb3JycGxvdC92aWduZXR0ZXMvY29ycnBsb3QtaW50cm8uaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIG1ha2UgbGFyZ2UgY29ycmVsYXRpb24gcGxvdHMKW0dHYWxseV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL0dHYWxseS9HR2FsbHkucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gbWFrZSBzbWFsbGVyIGNvcnJlbGF0aW9uIHBsb3RzICAKW3RpZHltb2RlbHNdKGh0dHBzOi8vd3d3LnRpZHltb2RlbHMub3JnKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gbG9hZCBpbiBhIHNldCBvZiBwYWNrYWdlcyAoYnJvb20sIGRpYWxzLCBpbmZlciwgcGFyc25pcCwgcHVycnIsIHJlY2lwZXMsIHJzYW1wbGUsIHRpYmJsZSwgeWFyZHN0aWNrKQpbcnNhbXBsZV0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yc2FtcGxlL2FydGljbGVzL0Jhc2ljcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBzcGxpdCB0aGUgZGF0YSBpbnRvIHRlc3RpbmcgYW5kIHRyYWluaW5nIHNldHM7IHRvIHNwbGl0IHRoZSB0cmFpbmluZyBzZXQgZm9yIGNyb3NzLXZhbGlkYXRpb24gIApbcmVjaXBlc10oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yZWNpcGVzLyl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gcHJlLXByb2Nlc3MgZGF0YSBmb3IgbW9kZWxpbmcgaW4gYSB0aWR5IGFuZCByZXByb2R1Y2libGUgd2F5IGFuZCB0byBleHRyYWN0IHByZS1wcm9jZXNzZWQgZGF0YSAobWFqb3IgZnVuY3Rpb25zIGFyZSBgcmVjaXBlKClgLCBgcHJlcCgpYCBhbmQgdmFyaW91cyB0cmFuc2Zvcm1hdGlvbiBgc3RlcF8qKClgIGZ1bmN0aW9ucywgYXMgd2VsbCBhcyBgYmFrZWAgd2hpY2ggZXh0cmFjdHMgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhICh1c2VkIHRvIHJlcXVpcmUgYGp1aWNlKClgKSBhbmQgYXBwbGllcyByZWNpcGUgcHJlcHJvY2Vzc2luZyBzdGVwcyB0byB0ZXN0aW5nIGRhdGEpLiBTZWUgW2hlcmVdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yZWNpcGVzL3JlY2lwZXMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9ICBmb3IgbW9yZSBpbmZvLgpbcGFyc25pcF0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9wYXJzbmlwLyl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgYW4gaW50ZXJmYWNlIHRvIGNyZWF0ZSBtb2RlbHMgKG1ham9yIGZ1bmN0aW9ucyBhcmUgYGZpdCgpYCwgYHNldF9lbmdpbmUoKWApClt5YXJkc3RpY2tdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8veWFyZHN0aWNrLyl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gZXZhbHVhdGUgdGhlIHBlcmZvcm1hbmNlIG9mIG1vZGVscwpbYnJvb21dKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvYmxvZy8yMDE4LzA3L2Jyb29tLTAtNS0wLyl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGdldCB0aWR5IG91dHB1dCBmb3Igb3VyIG1vZGVsIGZpdCBhbmQgcGVyZm9ybWFuY2UKW2dncGxvdDJdKGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIG1ha2UgdmlzdWFsaXphdGlvbnMgd2l0aCBtdWx0aXBsZSBsYXllcnMKW2RpYWxzXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnL2Jsb2cvMjAxOS8xMC9kaWFscy0wLTAtMy8pe3RhcmdldD0iX2JsYW5rIn0gfCB0byBzcGVjaWZ5IGh5cGVyLXBhcmFtZXRlciB0dW5pbmcKW3R1bmVdKGh0dHBzOi8vdHVuZS50aWR5bW9kZWxzLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gfCB0byBwZXJmb3JtIGNyb3NzIHZhbGlkYXRpb24sIHR1bmUgaHlwZXItcGFyYW1ldGVycywgYW5kIGdldCBwZXJmb3JtYW5jZSBtZXRyaWNzClt3b3JrZmxvd3NdKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy93b3JrZmxvd3MvdmVyc2lvbnMvMC4xLjEpe3RhcmdldD0iX2JsYW5rIn18IHRvIGNyZWF0ZSBtb2RlbGluZyB3b3JrZmxvdyB0byBzdHJlYW1saW5lIHRoZSBtb2RlbGluZyBwcm9jZXNzClt2aXBdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy92aXAvdmlwLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGNyZWF0ZSB2YXJpYWJsZSBpbXBvcnRhbmNlIHBsb3RzCltyYW5kb21Gb3Jlc3RdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yYW5kb21Gb3Jlc3QvcmFuZG9tRm9yZXN0LnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHBlcmZvcm0gdGhlIHJhbmRvbSBmb3Jlc3QgYW5hbHlzaXMKW2RvUGFyYWxsZWxdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9kb1BhcmFsbGVsL2RvUGFyYWxsZWwucGRmKSB8IHRvIGZpdCBjcm9zcyB2YWxpZGF0aW9uIHNhbXBsZXMgaW4gcGFyYWxsZWwgCltzdHJpbmdyXShodHRwczovL3N0cmluZ3IudGlkeXZlcnNlLm9yZy9hcnRpY2xlcy9zdHJpbmdyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgfCB0byBtYW5pcHVsYXRlIHRoZSB0ZXh0IHRoZSBtYXAgZGF0YQpbdGlkeXJdKGh0dHBzOi8vdGlkeXIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIHNlcGFyYXRlIGRhdGEgd2l0aGluIGEgY29sdW1uIGludG8gbXVsdGlwbGUgY29sdW1ucwpbcm5hdHVyYWxlYXJ0aF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JuYXR1cmFsZWFydGgvUkVBRE1FLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBnZXQgdGhlIGdlb21ldHJ5IGRhdGEgZm9yIHRoZSBlYXJ0aCB0byBwbG90IHRoZSBVUwpbbWFwc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hcHMvbWFwcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBnZXQgbWFwIGRhdGFiYXNlIGRhdGEgYWJvdXQgY291bnRpZXMgdG8gZHJhdyB0aGVtIG9uIG91ciBVUyBtYXAKW3NmXShodHRwczovL3Itc3BhdGlhbC5naXRodWIuaW8vc2YvKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gY29udmVydCB0aGUgbWFwIGRhdGEgaW50byBhIGRhdGEgZnJhbWUKW2x3Z2VvbV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2x3Z2VvbS9sd2dlb20ucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gdXNlIHRoZSBgc2ZgIGZ1bmN0aW9uIHRvIGNvbnZlcnQgbWFwIGdlb2dyYXBoaWNhbCBkYXRhCltyZ2Vvc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JnZW9zL3JnZW9zLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHVzZSBnZW9tZXRyeSBkYXRhCltwYXRjaHdvcmtdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9wYXRjaHdvcmsvcGF0Y2h3b3JrLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGFsbG93IHBsb3RzIHRvIGJlIGNvbWJpbmVkCl9fXwoKClRoZSBmaXJzdCB0aW1lIHdlIHVzZSBhIGZ1bmN0aW9uLCB3ZSB3aWxsIHVzZSB0aGUgYDo6YCB0byBpbmRpY2F0ZSB3aGljaCBwYWNrYWdlIHdlIGFyZSB1c2luZy4gClVubGVzcyB3ZSBoYXZlIG92ZXJsYXBwaW5nIGZ1bmN0aW9uIG5hbWVzLCB0aGlzIGlzIG5vdCBuZWNlc3NhcnksIGJ1dCB3ZSB3aWxsIGluY2x1ZGUgaXQgaGVyZSB0byBiZSBpbmZvcm1hdGl2ZSBhYm91dCB3aGVyZSB0aGUgZnVuY3Rpb25zIHdlIHdpbGwgdXNlIGNvbWUgZnJvbS4KCgojICoqQ29udGV4dCoqCioqKgoKVGhlIFtTdGF0ZSBvZiBHbG9iYWwgQWlyXShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gaXMgYSByZXBvcnQgcmVsZWFzZWQgZXZlcnkgeWVhciB0byBjb21tdW5pY2F0ZSB0aGUgaW1wYWN0IG9mIGFpciBwb2xsdXRpb24gb24gcHVibGljIGhlYWx0aC4gCgpUaGUgW1N0YXRlIG9mIEdsb2JhbCBBaXIgMjAxOSByZXBvcnRdKGh0dHBzOi8vd3d3LnN0YXRlb2ZnbG9iYWxhaXIub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvc29nYV8yMDE5X3JlcG9ydC5wZGYpe3RhcmdldD0iX2JsYW5rIn0Kd2hpY2ggdXNlcyBkYXRhIGZyb20gMjAxNyBzdGF0ZWQgdGhhdDoKCj4gQWlyIHBvbGx1dGlvbiBpcyB0aGUgKipmaWZ0aCoqIGxlYWRpbmcgcmlzayBmYWN0b3IgZm9yIG1vcnRhbGl0eSB3b3JsZHdpZGUuIEl0IGlzIHJlc3BvbnNpYmxlIGZvciBtb3JlCmRlYXRocyB0aGFuIG1hbnkgYmV0dGVyLWtub3duIHJpc2sgZmFjdG9ycyBzdWNoIGFzIG1hbG51dHJpdGlvbiwgYWxjb2hvbCB1c2UsIGFuZCBwaHlzaWNhbCBpbmFjdGl2aXR5LgpFYWNoIHllYXIsICoqbW9yZSoqIHBlb3BsZSBkaWUgZnJvbSBhaXIgcG9sbHV0aW9u4oCTcmVsYXRlZCBkaXNlYXNlIHRoYW4gZnJvbSByb2FkICoqdHJhZmZpYyBpbmp1cmllcyoqIG9yICoqbWFsYXJpYSoqLgoKPHAgYWxpZ249ImNlbnRlciI+CjxpbWcgd2lkdGg9IjYwMCIgc3JjPSJodHRwczovL3d3dy5oZWFsdGhlZmZlY3RzLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL1NvR0EtRmlndXJlcy0wMS5qcGciPgo8L3A+CgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LnN0YXRlb2ZnbG9iYWxhaXIub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvc29nYV8yMDE5X3JlcG9ydC5wZGYpe3RhcmdldD0iX2JsYW5rIn0KClRoZSByZXBvcnQgYWxzbyBzdGF0ZWQgdGhhdDoKCj4gSW4gMjAxNywgYWlyIHBvbGx1dGlvbiBpcyBlc3RpbWF0ZWQgdG8gaGF2ZSBjb250cmlidXRlZCB0byBjbG9zZSB0byA1IG1pbGxpb24KZGVhdGhzIGdsb2JhbGx5IOKAlCBuZWFybHkgKioxIGluIGV2ZXJ5IDEwIGRlYXRocyoqLgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIjIwMTdkZWF0aHMucG5nIikpCmBgYAoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3NvZ2FfMjAxOV9mYWN0X3NoZWV0LnBkZil7dGFyZ2V0PSJfYmxhbmsifQoKVGhlIFtTdGF0ZSBvZiBHbG9iYWwgQWlyIDIwMTggcmVwb3J0XShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3NvZ2EtMjAxOC1yZXBvcnQucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHVzaW5nIGRhdGEgZnJvbSAyMDE2IHdoaWNoIHNlcGFyYXRlZCBkaWZmZXJlbnQgdHlwZXMgb2YgYWlyIHBvbGx1dGlvbiwgZm91bmQgdGhhdCAqKnBhcnRpY3VsYXRlIHBvbGx1dGlvbiB3YXMgcGFydGljdWxhcmx5IGFzc29jaWF0ZWQgd2l0aCBtb3J0YWxpdHkqKi4KCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCIyMDE3bW9ydGFsaXR5LnBuZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhLTIwMTgtcmVwb3J0LnBkZil7dGFyZ2V0PSJfYmxhbmsifQoKVGhlIDIwMTkgcmVwb3J0IHNob3dzIHRoYXQgdGhlIGhpZ2hlc3QgbGV2ZWxzIG9mIGZpbmUgcGFydGljdWxhdGUgcG9sbHV0aW9uIG9jY3VycyBpbiBBZnJpY2EgYW5kIEFzaWEgYW5kIHRoYXQ6Cgo+IE1vcmUgdGhhbiAqKjkwJSoqIG9mIHBlb3BsZSB3b3JsZHdpZGUgbGl2ZSBpbiBhcmVhcyAqKmV4Y2VlZGluZyoqIHRoZSBXb3JsZCBIZWFsdGggT3JnYW5pemF0aW9uIChXSE8pICoqR3VpZGVsaW5lKiogZm9yIGhlYWx0aHkgYWlyLiBNb3JlIHRoYW4gaGFsZiBsaXZlIGluIGFyZWFzIHRoYXQgZG8gbm90IGV2ZW4gbWVldCBXSE8ncyBsZWFzdC1zdHJpbmdlbnQgYWlyIHF1YWxpdHkgdGFyZ2V0LgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIlBNd29ybGQucG5nIikpCmBgYAoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3NvZ2FfMjAxOV9mYWN0X3NoZWV0LnBkZil7dGFyZ2V0PSJfYmxhbmsifQoKTG9va2luZyBhdCB0aGUgVVMgc3BlY2lmaWNhbGx5LCBhaXIgcG9sbHV0aW9uIGxldmVscyBhcmUgZ2VuZXJhbGx5IGltcHJvdmluZywgd2l0aCBkZWNsaW5pbmcgbmF0aW9uYWwgYWlyIHBvbGx1dGFudCBjb25jZW50cmF0aW9uIGF2ZXJhZ2VzIGFzIHNob3duIGZyb20gdGhlIDIwMTkgWypPdXIgTmF0aW9uJ3MgQWlyKl0oaHR0cHM6Ly9naXNwdWIuZXBhLmdvdi9haXIvdHJlbmRzcmVwb3J0LzIwMTkvI2hvbWUpe3RhcmdldD0iX2JsYW5rIn0gcmVwb3J0IGZyb20gdGhlIFVTIEVudmlyb25tZW50YWwgUHJvdGVjdGlvbiBBZ2VuY3kgKEVQQSk6IAoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgIlVTLnBuZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9naXNwdWIuZXBhLmdvdi9haXIvdHJlbmRzcmVwb3J0LzIwMTkvZG9jdW1lbnRhdGlvbi9BaXJUcmVuZHNfRmx5ZXIucGRmKXt0YXJnZXQ9Il9ibGFuayJ9CgpIb3dldmVyLCBhaXIgcG9sbHV0aW9uICoqY29udGludWVzIHRvIGNvbnRyaWJ1dGUgdG8gaGVhbHRoIHJpc2sgZm9yIEFtZXJpY2FucyoqLCBpbiBwYXJ0aWN1bGFyIGluICoqcmVnaW9ucyB3aXRoIGhpZ2hlciB0aGFuIG5hdGlvbmFsIGF2ZXJhZ2UgcmF0ZXMqKiBvZiBwb2xsdXRpb24gdGhhdCBhY3R1YWxseSBhdCB0aW1lIGV4Y2VlZCB0aGUgV0hPJ3MgcmVjb21tZW5kZWQgbGV2ZWwuIApUaHVzLCBpdCBpcyBpbXBvcnRhbnQgdG8gb2J0YWluIGhpZ2ggc3BhdGlhbCBncmFudWxhcml0eSBpbiBlc3RpbWF0ZXMgb2YgYWlyIHBvbGx1dGlvbiBpbiBvcmRlciB0byBpZGVudGlmeSBsb2NhdGlvbnMgd2hlcmUgcG9wdWxhdGlvbnMgYXJlIGV4cGVyaWVuY2luZyBoYXJtZnVsIGxldmVscyBvZiBleHBvc3VyZS4KCllvdSBjYW4gc2VlIHRoYXQgY3VycmVudCBhaXIgcXVhbGl0eSBjb25kaXRpb25zIGF0IHRoaXMgW3dlYnNpdGVdKGh0dHBzOi8vYXFpY24ub3JnL2NpdHkvdXNhLyl7dGFyZ2V0PSJfYmxhbmsifSBhbmQgeW91IHdpbGwgbm90aWNlIHZhcmlhdGlvbiBhY3Jvc3MgZGlmZmVyZW50IGNpdGllcy4KCkZvciBleGFtcGxlLCBoZXJlIGFyZSB0aGUgY29uZGl0aW9ucyBpbiBUb3Bla2EgS2Fuc2FzIGF0IHRoZSB0aW1lIHRoaXMgY2FzZSBzdHVkeSB3YXMgY3JlYXRlZDoKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJLYW5zYXMucG5nIikpCmBgYAoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL2FxaWNuLm9yZy9jaXR5L3VzYS8pe3RhcmdldD0iX2JsYW5rIn0KCkl0IHJlcG9ydHMgcGFydGljdWxhdGUgdmFsdWVzIHVzaW5nIHdoYXQgaXMgY2FsbGVkIHRoZSBbQWlyIFF1YWxpdHkgSW5kZXhdKGh0dHBzOi8vd3d3LmFpcm5vdy5nb3YvaW5kZXguY2ZtP2FjdGlvbj1hcWliYXNpY3MuYXFpKXt0YXJnZXQ9Il9ibGFuayJ9IChBUUkpLgpUaGlzIFtjYWxjdWxhdG9yXShodHRwczovL2Fpcm5vdy5nb3YvaW5kZXguY2ZtP2FjdGlvbj1haXJub3cuY2FsY3VsYXRvcil7dGFyZ2V0PSJfYmxhbmsifSBpbmRpY2F0ZXMgdGhhdCAxMTQgQVFJIGlzIGVxdWl2YWxlbnQgdG8gNDAuNyB1Zy9tXjNeIGFuZCBpcyBjb25zaWRlcmVkIHVuaGVhbHRoeSBmb3Igc2Vuc2l0aXZlIGluZGl2aWR1YWxzLgpUaHVzLCBzb21lIGFyZWFzIGV4Y2VlZCB0aGUgV0hPIGFubnVhbCBleHBvc3VyZSBndWlkZWxpbmUgKDEwIHVnL21eM14pIGFuZCB0aGlzIG1heSBhZHZlcnNlbHkgYWZmZWN0IHRoZSBoZWFsdGggb2YgcGVvcGxlIGxpdmluZyBpbiB0aGVzZSBsb2NhdGlvbnMuCgpBZHZlcnNlIGhlYWx0aCBlZmZlY3RzIGhhdmUgYmVlbiBhc3NvY2lhdGVkIHdpdGggcG9wdWxhdGlvbnMgZXhwZXJpZW5jaW5nIGhpZ2hlciBwb2xsdXRpb24gZXhwb3N1cmUgZGVzcGl0ZSB0aGUgbGV2ZWxzIGJlaW5nIGJlbG93IHN1Z2dlc3RlZCBndWlkZWxpbmVzLiAKQWxzbywgaXQgYXBwZWFycyB0aGF0IHRoZSBjb21wb3NpdGlvbiBvZiB0aGUgcGFydGljdWxhdGUgbWF0dGVyIGFuZCB0aGUgaW5mbHVlbmNlIG9mIG90aGVyIGRlbW9ncmFwaGljIGZhY3RvcnMgbWF5IG1ha2Ugc3BlY2lmaWMgcG9wdWxhdGlvbnMgbW9yZSBhdCByaXNrIGZvciBhZHZlcnNlIGhlYWx0aCBlZmZlY3RzIGR1ZSB0byBhaXIgcG9sbHV0aW9uLiAKRm9yIGV4YW1wbGUsIHNlZSB0aGlzIFthcnRpY2xlXShodHRwczovL3d3dy5uZWptLm9yZy9kb2kvZnVsbC8xMC4xMDU2L05FSk1vYTE3MDI3NDcpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgZGV0YWlscy4KClRoZSBtb25pdG9yIGRhdGEgdGhhdCB3ZSB3aWxsIHVzZSBpbiB0aGlzIGNhc2Ugc3R1ZHkgY29tZSBmcm9tIGEgc3lzdGVtIG9mIG1vbml0b3JzIGluIHdoaWNoIHJvdWdobHkgOTAlIGFyZSBsb2NhdGVkIHdpdGhpbiBjaXRpZXMuIApIZW5jZSwgdGhlcmUgaXMgYW4gKiplcXVpdHkgaXNzdWUqKiBpbiB0ZXJtcyBvZiBjYXB0dXJpbmcgdGhlIGFpciBwb2xsdXRpb24gbGV2ZWxzIG9mIG1vcmUgcnVyYWwgYXJlYXMuIApUbyBnZXQgYSBiZXR0ZXIgc2Vuc2Ugb2YgdGhlIHBvbGx1dGlvbiBleHBvc3VyZXMgZm9yIHRoZSBpbmRpdmlkdWFscyBsaXZpbmcgaW4gdGhlc2UgYXJlYXMsIG1ldGhvZHMgbGlrZSBtYWNoaW5lIGxlYXJuaW5nIGNhbiBiZSB1c2VmdWwgdG8gZXN0aW1hdGUgYWlyIHBvbGx1dGlvbiBsZXZlbHMgaW4gKiphcmVhcyB3aXRoIGxpdHRsZSB0byBubyBtb25pdG9yaW5nKiouIApTcGVjaWZpY2FsbHksIHRoZXNlIG1ldGhvZHMgY2FuIGJlIHVzZWQgdG8gZXN0aW1hdGUgYWlyIHBvbGx1dGlvbiBpbiB0aGVzZSBsb3cgbW9uaXRvcmluZyBhcmVhcyBzbyB0aGF0IHdlIGNhbiBtYWtlIGEgbWFwIGxpa2UgdGhpcyB3aGVyZSB3ZSBoYXZlIGFubnVhbCBlc3RpbWF0ZXMgZm9yIGFsbCBvZiB0aGUgY29udGlndW91cyBVUzoKCjxwIGFsaWduPSJjZW50ZXIiPgogIDxpbWcgd2lkdGg9IjYwMCIgc3JjPSJodHRwczovL2FyYy1hbmdsZXJmaXNoLXdhc2hwb3N0LXByb2Qtd2FzaHBvc3QuczMuYW1hem9uYXdzLmNvbS9wdWJsaWMvU0FXT0VHQlhNVkdRN0FTNVBaNlVVT1g2RlkucG5nIj4KPC9wPgoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5nb29nbGUuY29tL3VybD9zYT1pJnVybD1odHRwcyUzQSUyRiUyRnd3dy53YXNoaW5ndG9ucG9zdC5jb20lMkZidXNpbmVzcyUyRjIwMTklMkYxMCUyRjIzJTJGYWlyLXBvbGx1dGlvbi1pcy1nZXR0aW5nLXdvcnNlLWRhdGEtc2hvdy1tb3JlLXBlb3BsZS1hcmUtZHlpbmclMkYmcHNpZz1BT3ZWYXczdi1aRFRCUG5MUDJNWXRLZjNVbmRqJnVzdD0xNTg1Nzg0NDc5MDY4MDAwJnNvdXJjZT1pbWFnZXMmY2Q9dmZlJnZlZD0wQ0FJUWpSeHFGd29UQ1BDeW45Znh4ZWdDRlFBQUFBQWRBQUFBQUJBZCl7dGFyZ2V0PSJfYmxhbmsifQoKVGhpcyBpcyB3aGF0IHdlIGFpbSB0byBhY2hpZXZlIGluIHRoaXMgY2FzZSBzdHVkeS4KCiMgKipMaW1pdGF0aW9ucyoqCioqKgoKVGhlcmUgYXJlIHNvbWUgaW1wb3J0YW50IGNvbnNpZGVyYXRpb25zIHJlZ2FyZGluZyB0aGUgZGF0YSBhbmFseXNpcyBpbiB0aGlzIGNhc2Ugc3R1ZHkgdG8ga2VlcCBpbiBtaW5kOiAKCjEuIFRoZSBkYXRhIGRvIG5vdCBpbmNsdWRlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBjb21wb3NpdGlvbiBvZiBwYXJ0aWN1bGF0ZSBtYXR0ZXIuIERpZmZlcmVudCB0eXBlcyBvZiBwYXJ0aWN1bGF0ZXMgbWF5IGJlIG1vcmUgYmVuaWduIG9yIGRlbGV0ZXJpb3VzIGZvciBoZWFsdGggb3V0Y29tZXMuCgoyLiBPdXRkb29yIHBvbGx1dGlvbiBsZXZlbHMgYXJlIG5vdCBuZWNlc3NhcmlseSBhbiBpbmRpY2F0aW9uIG9mIGluZGl2aWR1YWwgZXhwb3N1cmVzLiBQZW9wbGUgc3BlbmQgZGlmZmVyaW5nIGFtb3VudHMgb2YgdGltZSBpbmRvb3JzIGFuZCBvdXRkb29ycyBhbmQgYXJlIGV4cG9zZWQgdG8gZGlmZmVyZW50IHBvbGx1dGlvbiBsZXZlbHMgaW5kb29ycy4gUmVzZWFyY2hlcnMgYXJlIG5vdyBkZXZlbG9waW5nIHBlcnNvbmFsIG1vbml0b3Jpbmcgc3lzdGVtcyB0byB0cmFjayBhaXIgcG9sbHV0aW9uIGxldmVscyBvbiB0aGUgcGVyc29uYWwgbGV2ZWwuCgozLiBPdXIgYW5hbHlzaXMgd2lsbCB1c2UgYW5udWFsIG1lYW4gZXN0aW1hdGVzIG9mIHBvbGx1dGlvbiBsZXZlbHMsIGJ1dCB0aGVzZSBjYW4gdmFyeSBncmVhdGx5IGJ5IHNlYXNvbiwgZGF5IGFuZCBldmVuIGhvdXIuIFRoZXJlIGFyZSBkYXRhIHNvdXJjZXMgdGhhdCBoYXZlIGZpbmVyIGxldmVscyBvZiB0ZW1wb3JhbCBkYXRhLCBob3dldmVyIHdlIGFyZSBpbnRlcmVzdGVkIGluIGxvbmcgdGVybSBleHBvc3VyZXMsIGFzIHRoZXNlIGFwcGVhciB0byBiZSB0aGUgbW9zdCBpbmZsdWVudGlhbCBmb3IgaGVhbHRoIG91dGNvbWVzLCBzbyB3ZSBjaG9zZSB0byB1c2UgYW5udWFsIGxldmVsIGRhdGEuIAoKCiMgKipXaGF0IGFyZSB0aGUgZGF0YT8qKiB7I3doYXRhcmV0aGVkYXRhfQoqKioKCldoZW4gdXNpbmcgbWFjaGluZSBsZWFybmluZyBmb3IgcHJlZGljdGlvbiwgdGhlcmUgYXJlIHR3byBtYWluIHR5cGVzIG9mIGRhdGEgb2YgaW50ZXJlc3Q6CgoxLiBBbiAqKmNvbnRpbnVvdXMqKiBvdXRjb21lIHZhcmlhYmxlIHRoYXQgd2Ugd2FudCB0byBwcmVkaWN0IAoyLiBBIHNldCBvZiBmZWF0dXJlKHMpIChvciBwcmVkaWN0b3IgdmFyaWFibGVzKSB0aGF0IHdlIHVzZSB0byBwcmVkaWN0IHRoZSBvdXRjb21lIHZhcmlhYmxlCgpUaGUgKipvdXRjb21lIHZhcmlhYmxlKiogaXMgd2hhdCBhcmUgdHJ5aW5nIHRvICoqcHJlZGljdCoqLiAKVG8gYnVpbGQgKG9yIHRyYWluKSBvdXIgbW9kZWwsIHdlIHVzZSBib3RoIHRoZSBvdXRjb21lIGFuZCBmZWF0dXJlcy4KVGhlIGdvYWwgaXMgdG8gaWRlbnRpZnkgaW5mb3JtYXRpdmUgZmVhdHVyZXMgdGhhdCBjYW4gZXhwbGFpbiBhIGxhcmdlIGFtb3VudCBvZiB2YXJpYXRpb24gaW4gb3VyIG91dGNvbWUgdmFyaWFibGUuIApVc2luZyB0aGlzIG1vZGVsLCB3ZSBjYW4gdGhlbiBwcmVkaWN0IHRoZSBvdXRjb21lIGZyb20gbmV3IG9ic2VydmF0aW9ucyB3aXRoIHRoZSBzYW1lIGZlYXR1cmVzIHdoZXJlIGhhdmUgbm90IG9ic2VydmVkIHRoZSBvdXRjb21lLiAKCkFzIGEgc2ltcGxlIGV4YW1wbGUsIGltYWdpbmUgdGhhdCB3ZSBoYXZlIGRhdGEgYWJvdXQgdGhlIHNhbGVzIGFuZCBjaGFyYWN0ZXJpc3RpY3Mgb2YgY2FycyBmcm9tIGxhc3QgeWVhciBhbmQgd2Ugd2FudCB0byBwcmVkaWN0IHdoaWNoIGNhcnMgbWlnaHQgc2VsbCB3ZWxsIHRoaXMgeWVhci4gCldlIGRvIG5vdCBoYXZlIHRoZSBzYWxlcyBkYXRhIHlldCBmb3IgdGhpcyB5ZWFyLCBidXQgd2UgZG8ga25vdyB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIG91ciBjYXJzIGZvciB0aGlzIHllYXIuIApXZSBjYW4gYnVpbGQgYSBtb2RlbCBvZiB0aGUgY2hhcmFjdGVyaXN0aWNzIHRoYXQgZXhwbGFpbmVkIHNhbGVzIGxhc3QgeWVhciB0byBlc3RpbWF0ZSB3aGF0IGNhcnMgbWlnaHQgc2VsbCB3ZWxsIHRoaXMgeWVhci4gCkluIHRoaXMgY2FzZSwgb3VyIG91dGNvbWUgdmFyaWFibGUgaXMgdGhlIHNhbGVzIG9mIGNhcnMsIHdoaWxlIHRoZSBkaWZmZXJlbnQgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBjYXJzIG1ha2UgdXAgb3VyIGZlYXR1cmVzLgoKIyMjIFN0YXJ0IHdpdGggYSBxdWVzdGlvbgoKVGhpcyBpcyB0aGUgbW9zdCBjb21tb25seSBtaXNzZWQgc3RlcCB3aGVuIGRldmVsb3BpbmcgYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobS4gCk1hY2hpbmUgbGVhcm5pbmcgY2FuIHZlcnkgZWFzaWx5IGJlIHR1cm5lZCBpbnRvIGFuIGVuZ2luZWVyaW5nIHByb2JsZW0uIApKdXN0IGR1bXAgdGhlIG91dGNvbWUgYW5kIHRoZSBmZWF0dXJlcyBpbnRvIGEgYmxhY2sgYm94IGFsZ29yaXRobSBhbmQgdmlvbGEhIApCdXQgdGhpcyBraW5kIG9mIHRoaW5raW5nIGNhbiBsZWFkIHRvIG1ham9yIHByb2JsZW1zLiBJbiBnZW5lcmFsIGdvb2QgbWFjaGluZSBsZWFybmluZyBxdWVzdGlvbnM6CgoxLiBIYXZlIGEgcGxhdXNpYmxlIGV4cGxhbmF0aW9uIGZvciB3aHkgdGhlIGZlYXR1cmVzIHByZWRpY3QgdGhlIG91dGNvbWUuIAoyLiBDb25zaWRlciBwb3RlbnRpYWwgdmFyaWF0aW9uIGluIGJvdGggdGhlIGZlYXR1cmVzIGFuZCB0aGUgb3V0Y29tZSBvdmVyIHRpbWUKMy4gQXJlIGNvbnNpc3RlbnRseSByZS1ldmFsdWF0ZWQgb24gY3JpdGVyaWEgMSBhbmQgMiBvdmVyIHRpbWUuIAoKSW4gdGhpcyBjYXNlIHN0dWR5LCB3ZSB3YW50IHRvICoqcHJlZGljdCoqIGFpciBwb2xsdXRpb24gbGV2ZWxzLiAKVG8gYnVpbGQgdGhpcyBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSwgb3VyICoqb3V0Y29tZSB2YXJpYWJsZSoqIGlzIGZpbmUgcGFydGljdWxhdGUgbWF0dGVyIChQTX4yLjV+KSBjYXB0dXJlZCBmcm9tIGFpciBwb2xsdXRpb24gbW9uaXRvcnMgaW4gdGhlIGNvbnRpZ3VvdXMgVVMgZnJvbSAyMDA4LiAKT3VyICoqZmVhdHVyZXMqKiAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykgaW5jbHVkZSBkYXRhIGFib3V0IHBvcHVsYXRpb24gZGVuc2l0eSwgcm9hZCBkZW5zaXR5LCB1cmJhbml6YXRpb24gbGV2ZWxzLCBhbmQgTkFTQSBzYXRlbGxpdGUgZGF0YS4gCgpBbGwgb2Ygb3VyIGRhdGEgd2FzIHByZXZpb3VzbHkgY29sbGVjdGVkIGJ5IGEgW3Jlc2VhcmNoZXJdKGh0dHA6Ly93d3cuYmlvc3RhdC5qaHNwaC5lZHUvfnJwZW5nLykgYXQgdGhlIFtKb2hucyBIb3BraW5zIFNjaG9vbCBvZiBQdWJsaWMgSGVhbHRoXShodHRwczovL3d3dy5qaHNwaC5lZHUvKSB3aG8gc3R1ZGllcyBhaXIgcG9sbHV0aW9uIGFuZCBjbGltYXRlIGNoYW5nZS4gCgoKIyMjIE91ciBvdXRjb21lIHZhcmlhYmxlCgpUaGUgbW9uaXRvciBkYXRhIHRoYXQgd2Ugd2lsbCBiZSB1c2luZyBjb21lcyBmcm9tICoqW2dyYXZpbWV0cmljIG1vbml0b3JzXShodHRwczovL3B1YmxpY2xhYi5vcmcvd2lraS9maWx0ZXItcG0pe3RhcmdldD0iX2JsYW5rIn0qKiAoc2VlIHBpY3R1cmUgYmVsb3cpIG9wZXJhdGVkIGJ5IHRoZSBVUyBbRW52aXJvbm1lbnRhbCBQcm90ZWN0aW9uIEFnZW5jeSAoRVBBKV0oaHR0cHM6Ly93d3cuZXBhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0uCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjEwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwibW9uaXRvci5wbmciKSkKYGBgCgojIyMjIyBbaW1hZ2UgY3VydGVzeSBvZiBbS2lyc3RlbiBLb2VobGVyXShodHRwczovL3d3dy5qaHNwaC5lZHUvZmFjdWx0eS9kaXJlY3RvcnkvcHJvZmlsZS8yOTI4L2tpcnN0ZW4ta29laGxlcildCgpUaGVzZSBtb25pdG9ycyB1c2UgYSBmaWx0cmF0aW9uIHN5c3RlbSB0byBzcGVjaWZpY2FsbHkgY2FwdHVyZSBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlci4gCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjE1MHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiZmlsdGVyLnBuZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9wdWJsaWNsYWIub3JnL3dpa2kvZmlsdGVyLXBtKXt0YXJnZXQ9Il9ibGFuayJ9CgpUaGUgd2VpZ2h0IG9mIHRoaXMgcGFydGljdWxhdGUgbWF0dGVyIGlzIG1hbnVhbGx5IG1lYXN1cmVkIGRhaWx5IG9yIHdlZWtseS4gCkZvciB0aGUgRVBBIHN0YW5kYXJkIG9wZXJhdGluZyBwcm9jZWR1cmUgZm9yIFBNIGdyYXZpbWV0cmljIGFuYWx5c2lzIGluIDIwMDgsIHdlIHJlZmVyIHRoZSByZWFkZXIgdG8gW2hlcmVdKGh0dHBzOi8vd3d3My5lcGEuZ292L3R0bmFtdGkxL2ZpbGVzL2FtYmllbnQvcG0yNS9zcGVjL1JUSUdyYXZNYXNzU09QRklOQUwucGRmKXt0YXJnZXQ9Il9ibGFuayJ9LgoKPGRldGFpbHM+PHN1bW1hcnk+Rm9yIG1vcmUgb24gR3JhdmltZXRyaWMgYW5hbHlzaXMsIHlvdSBjYW4gZXhwYW5kIGhlcmUgPC9zdW1tYXJ5PgoKR3JhdmltZXRyaWMgYW5hbHlzaXMgaXMgYWxzbyB1c2VkIGZvciBbZW1pc3Npb24gdGVzdGluZ10oaHR0cHM6Ly93d3cubXQuY29tL3VzL2VuL2hvbWUvYXBwbGljYXRpb25zL0xhYm9yYXRvcnlfd2VpZ2hpbmcvZW1pc3Npb25zLXRlc3RpbmctcGFydGljdWxhdGUtbWF0dGVyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0uIApUaGUgc2FtZSBpZGVhIGFwcGxpZXM6IGEgZnJlc2ggZmlsdGVyIGlzIGFwcGxpZWQgYW5kIHRoZSBkZXNpcmVkIGFtb3VudCBvZiB0aW1lIHBhc3NlcywgdGhlbiB0aGUgZmlsdGVyIGlzIHJlbW92ZWQgYW5kIHdlaWdoZWQuIAoKVGhlcmUgYXJlIFtvdGhlciBtb25pdG9yaW5nIHN5c3RlbXNdKGh0dHBzOi8vd3d3LnNlbnNpcmlvbi5jb20vZW4vYWJvdXQtdXMvbmV3c3Jvb20vc2Vuc2lyaW9uLXNwZWNpYWxpc3QtYXJ0aWNsZXMvcGFydGljdWxhdGUtbWF0dGVyLXNlbnNpbmctZm9yLWFpci1xdWFsaXR5LW1lYXN1cmVtZW50cy8pe3RhcmdldD0iX2JsYW5rIn0gdGhhdCBjYW4gcHJvdmlkZSBob3VybHkgbWVhc3VyZW1lbnRzLCBidXQgd2Ugd2lsbCBub3QgYmUgdXNpbmcgZGF0YSBmcm9tIHRoZXNlIG1vbml0b3JzIGluIG91ciBhbmFseXNpcy4gCkdyYXZpbWV0cmljIGFuYWx5c2lzIGlzIGNvbnNpZGVyZWQgdG8gYmUgYW1vbmcgdGhlIG1vc3QgYWNjdXJhdGUgbWV0aG9kcyBmb3IgbWVhc3VyaW5nIHBhcnRpY3VsYXRlIG1hdHRlci4KCjwvZGV0YWlscz4KCkluIG91ciBkYXRhIHNldCwgdGhlIGB2YWx1ZWAgY29sdW1uIGluZGljYXRlcyB0aGUgUE1+Mi41fiBtb25pdG9yIGF2ZXJhZ2UgZm9yIDIwMDggaW4gbWFzcyBvZiBmaW5lIHBhcnRpY2xlcy92b2x1bWUgb2YgYWlyIGZvciA4NzYgZ3JhdmltZXRyaWMgbW9uaXRvcnMuIApUaGUgdW5pdHMgYXJlIG1pY3JvZ3JhbXMgb2YgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIgKFBNKSB0aGF0IGlzIGxlc3MgdGhhbiAyLjUgbWljcm9tZXRlcnMgaW4gZGlhbWV0ZXIgcGVyIGN1YmljIG1ldGVyIG9mIGFpciAtIG1hc3MgY29uY2VudHJhdGlvbiAodWcvbV4zXikuClJlY2FsbCB0aGUgV0hPIGV4cG9zdXJlIGd1aWRlbGluZSBpcyA8IDEwIHVnL21eM14gb24gYXZlcmFnZSBhbm51YWxseSBmb3IgUE1+Mi41fi4KCiMjIyBPdXIgZmVhdHVyZXMgKHByZWRpY3RvciB2YXJpYWJsZXMpIAoKVGhlcmUgYXJlIDQ4IGZlYXR1cmVzIHdpdGggdmFsdWVzIGZvciBlYWNoIG9mIHRoZSA4NzYgbW9uaXRvcnMgKG9ic2VydmF0aW9ucykuIApUaGUgZGF0YSBjb21lcyBmcm9tIHRoZSBVUyBbRW52aXJvbm1lbnRhbCBQcm90ZWN0aW9uIEFnZW5jeSAoRVBBKV0oaHR0cHM6Ly93d3cuZXBhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0sIHRoZSBbTmF0aW9uYWwgQWVyb25hdXRpY3MgYW5kIFNwYWNlIEFkbWluaXN0cmF0aW9uIChOQVNBKV0oaHR0cHM6Ly93d3cubmFzYS5nb3YvKXt0YXJnZXQ9Il9ibGFuayJ9LCB0aGUgVVMgW0NlbnN1c10oaHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9hYm91dC93aGF0L2NlbnN1cy1hdC1hLWdsYW5jZS5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9LCBhbmQgdGhlIFtOYXRpb25hbCBDZW50ZXIgZm9yIEhlYWx0aCBTdGF0aXN0aWNzIChOQ0hTKV0oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2Fib3V0L2luZGV4Lmh0bSl7dGFyZ2V0PSJfYmxhbmsifS4KCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHNlZSBhIHRhYmxlIGFib3V0IHRoZSBzZXQgb2YgZmVhdHVyZXMgPC9zdW1tYXJ5PgoKVmFyaWFibGUgICB8IERldGFpbHMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQoqKmlkKiogIHwgTW9uaXRvciBudW1iZXIgIDxicj4gLS0gdGhlIGNvdW50eSBudW1iZXIgaXMgaW5kaWNhdGVkIGJlZm9yZSB0aGUgZGVjaW1hbCA8YnI+IC0tIHRoZSBtb25pdG9yIG51bWJlciBpcyBpbmRpY2F0ZWQgYWZ0ZXIgdGhlIGRlY2ltYWwgPGJyPiAgKipFeGFtcGxlKio6IDEwNzMuMDAyMyAgaXMgSmVmZmVyc29uIGNvdW50eSAoMTA3MykgYW5kIC4wMDIzIG9uZSBvZiA4IG1vbml0b3JzIAoqKmZpcHMqKiB8IEZlZGVyYWwgaW5mb3JtYXRpb24gcHJvY2Vzc2luZyBzdGFuZGFyZCBudW1iZXIgZm9yIHRoZSBjb3VudHkgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZCA8YnI+IC0tIDUgZGlnaXQgaWQgY29kZSBmb3IgY291bnRpZXMgKHplcm8gaXMgb2Z0ZW4gdGhlIGZpcnN0IHZhbHVlIGFuZCBzb21ldGltZXMgaXMgbm90IHNob3duKSA8YnI+IC0tIHRoZSBmaXJzdCAyIG51bWJlcnMgaW5kaWNhdGUgdGhlIHN0YXRlIDxicj4gLS0gdGhlIGxhc3QgdGhyZWUgbnVtYmVycyBpbmRpY2F0ZSB0aGUgY291bnR5IDxicj4gICoqRXhhbXBsZSoqOiBBbGFiYW1hJ3Mgc3RhdGUgY29kZSBpcyAwMSBiZWNhdXNlIGl0IGlzIGZpcnN0IGFscGhhYmV0aWNhbGx5IDxicj4gKG5vdGU6IEFsYXNrYSBhbmQgSGF3YWlpIGFyZSBub3QgaW5jbHVkZWQgYmVjYXVzZSB0aGV5IGFyZSBub3QgcGFydCBvZiB0aGUgY29udGlndW91cyBVUykgIAoqKkxhdCoqIHwgTGF0aXR1ZGUgb2YgdGhlIG1vbml0b3IgaW4gZGVncmVlcyAgCioqTG9uKiogfCBMb25naXR1ZGUgb2YgdGhlIG1vbml0b3IgaW4gZGVncmVlcyAgCioqc3RhdGUqKiB8IFN0YXRlIHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQKKipjb3VudHkqKiB8IENvdW50eSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkCioqY2l0eSoqIHwgQ2l0eSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkCioqQ01BUSoqICB8IEVzdGltYXRlZCB2YWx1ZXMgb2YgYWlyIHBvbGx1dGlvbiBmcm9tIGEgY29tcHV0YXRpb25hbCBtb2RlbCBjYWxsZWQgWyoqQ29tbXVuaXR5IE11bHRpc2NhbGUgQWlyIFF1YWxpdHkgKENNQVEpKipdKGh0dHBzOi8vd3d3LmVwYS5nb3YvY21hcSl7dGFyZ2V0PSJfYmxhbmsifSA8YnI+IC0tICBBIG1vbml0b3Jpbmcgc3lzdGVtIHRoYXQgc2ltdWxhdGVzIHRoZSBwaHlzaWNzIG9mIHRoZSBhdG1vc3BoZXJlIHVzaW5nIGNoZW1pc3RyeSBhbmQgd2VhdGhlciBkYXRhIHRvIHByZWRpY3QgdGhlIGFpciBwb2xsdXRpb24gPGJyPiAtLSAqKipEb2VzIG5vdCB1c2UgYW55IG9mIHRoZSBQTX4yLjV+IGdyYXZpbWV0cmljIG1vbml0b3JpbmcgZGF0YS4qKiogKFRoZXJlIGlzIGEgdmVyc2lvbiB0aGF0IGRvZXMgdXNlIHRoZSBncmF2aW1ldHJpYyBtb25pdG9yaW5nIGRhdGEsIGJ1dCBub3QgdGhpcyBvbmUhKSA8YnI+IC0tIERhdGEgZnJvbSB0aGUgRVBBCioqemN0YSoqIHwgW1ppcCBDb2RlIFRhYnVsYXRpb24gQXJlYV0oaHR0cHM6Ly93d3cyLmNlbnN1cy5nb3YvZ2VvL3BkZnMvZWR1Y2F0aW9uL2Jyb2NodXJlcy9aQ1RBcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZCA8YnI+IC0tIFBvc3RhbCBaaXAgY29kZXMgYXJlIGNvbnZlcnRlZCBpbnRvICJnZW5lcmFsaXplZCBhcmVhbCByZXByZXNlbnRhdGlvbnMiIHRoYXQgYXJlIG5vbi1vdmVybGFwcGluZyAgPGJyPiAtLSBEYXRhIGZyb20gdGhlIDIwMTAgQ2Vuc3VzICAKKip6Y3RhX2FyZWEqKiB8IExhbmQgYXJlYSBvZiB0aGUgemlwIGNvZGUgYXJlYSBpbiBtZXRlcnMgc3F1YXJlZCAgPGJyPiAtLSBEYXRhIGZyb20gdGhlIDIwMTAgQ2Vuc3VzICAKKip6Y3RhX3BvcCoqIHwgUG9wdWxhdGlvbiBpbiB0aGUgemlwIGNvZGUgYXJlYSAgPGJyPiAtLSBEYXRhIGZyb20gdGhlIDIwMTAgQ2Vuc3VzICAKKippbXBfYTUwMCoqIHwgSW1wZXJ2aW91cyBzdXJmYWNlIG1lYXN1cmUgPGJyPiAtLSBXaXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciA8YnI+IC0tIEltcGVydmlvdXMgc3VyZmFjZSBhcmUgcm9hZHMsIGNvbmNyZXRlLCBwYXJraW5nIGxvdHMsIGJ1aWxkaW5ncyA8YnI+IC0tIFRoaXMgaXMgYSBtZWFzdXJlIG9mIGRldmVsb3BtZW50IAoqKmltcF9hMTAwMCoqIHwgSW1wZXJ2aW91cyBzdXJmYWNlIG1lYXN1cmUgPGJyPiAtLSAgV2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yCioqaW1wX2E1MDAwKiogfCBJbXBlcnZpb3VzIHN1cmZhY2UgbWVhc3VyZSA8YnI+IC0tICBXaXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgIAoqKmltcF9hMTAwMDAqKiB8IEltcGVydmlvdXMgc3VyZmFjZSBtZWFzdXJlIDxicj4gLS0gIFdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgICAKKippbXBfYTE1MDAwKiogfCBJbXBlcnZpb3VzIHN1cmZhY2UgbWVhc3VyZSA8YnI+IC0tICBXaXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yICAKKipjb3VudHlfYXJlYSoqIHwgTGFuZCBhcmVhIG9mIHRoZSBjb3VudHkgb2YgdGhlIG1vbml0b3IgaW4gbWV0ZXJzIHNxdWFyZWQgIAoqKmNvdW50eV9wb3AqKiB8IFBvcHVsYXRpb24gb2YgdGhlIGNvdW50eSBvZiB0aGUgbW9uaXRvciAgCioqTG9nX2Rpc3RfdG9fcHJpc2VjKiogfCBMb2cgKE5hdHVyYWwgbG9nKSBkaXN0YW5jZSB0byBhIHByaW1hcnkgb3Igc2Vjb25kYXJ5IHJvYWQgZnJvbSB0aGUgbW9uaXRvciA8YnI+IC0tIEhpZ2h3YXkgb3IgbWFqb3Igcm9hZCAgCioqbG9nX3ByaV9sZW5ndGhfNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSA8YnI+IC0tIEhpZ2h3YXlzIG9ubHkgIAoqKmxvZ19wcmlfbGVuZ3RoXzEwMDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSA8YnI+IC0tIEhpZ2h3YXlzIG9ubHkgIAoqKmxvZ19wcmlfbGVuZ3RoXzE1MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDE1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSA8YnI+IC0tIEhpZ2h3YXlzIG9ubHkgIAoqKmxvZ19wcmlfbGVuZ3RoXzI1MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDI1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSA8YnI+IC0tIEhpZ2h3YXlzIG9ubHkgIAoqKmxvZ19wcmlzZWNfbGVuZ3RoXzUwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDUwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICAKKipsb2dfcHJpc2VjX2xlbmd0aF8xMDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICAKKipsb2dfcHJpc2VjX2xlbmd0aF81MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICAKKipsb2dfcHJpc2VjX2xlbmd0aF8xMDAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgPGJyPiAtLSBIaWdod2F5IGFuZCBzZWNvbmRhcnkgcm9hZHMgIAoqKmxvZ19wcmlzZWNfbGVuZ3RoXzE1MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICA8YnI+IC0tIEhpZ2h3YXkgYW5kIHNlY29uZGFyeSByb2FkcyAgCioqbG9nX3ByaXNlY19sZW5ndGhfMjUwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAyNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICAgICAgCioqbG9nX25laV8yMDA4X3BtMjVfc3VtXzEwMDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAKKipsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTUwMDAqKiB8IFRvbnMgb2YgZW1pc3Npb25zIGZyb20gbWFqb3Igc291cmNlcyBkYXRhIGJhc2UgKGFubnVhbCBkYXRhKSBzdW0gb2YgYWxsIHNvdXJjZXMgd2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTUwMDAgbWV0ZXJzIG9mIGRpc3RhbmNlIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICAgICAKKipsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMjUwMDAqKiB8IFRvbnMgb2YgZW1pc3Npb25zIGZyb20gbWFqb3Igc291cmNlcyBkYXRhIGJhc2UgKGFubnVhbCBkYXRhKSBzdW0gb2YgYWxsIHNvdXJjZXMgd2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMjUwMDAgbWV0ZXJzIG9mIGRpc3RhbmNlIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICAgICAKKipsb2dfbmVpXzIwMDhfcG0xMF9zdW1fMTAwMDAqKiB8IFRvbnMgb2YgZW1pc3Npb25zIGZyb20gbWFqb3Igc291cmNlcyBkYXRhIGJhc2UgKGFubnVhbCBkYXRhKSBzdW0gb2YgYWxsIHNvdXJjZXMgd2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTAwMDAgbWV0ZXJzIG9mIGRpc3RhbmNlIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICAgICAgCioqbG9nX25laV8yMDA4X3BtMTBfc3VtXzE1MDAwKip8IFRvbnMgb2YgZW1pc3Npb25zIGZyb20gbWFqb3Igc291cmNlcyBkYXRhIGJhc2UgKGFubnVhbCBkYXRhKSBzdW0gb2YgYWxsIHNvdXJjZXMgd2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTUwMDAgbWV0ZXJzIG9mIGRpc3RhbmNlIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICAgICAgCioqbG9nX25laV8yMDA4X3BtMTBfc3VtXzI1MDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDI1MDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgIAoqKnBvcGRlbnNfY291bnR5KiogfCBQb3B1bGF0aW9uIGRlbnNpdHkgKG51bWJlciBvZiBwZW9wbGUgcGVyIGtpbG9tZXRlciBzcXVhcmVkIGFyZWEgb2YgdGhlIGNvdW50eSkKKipwb3BkZW5zX3pjdGEqKiB8IFBvcHVsYXRpb24gZGVuc2l0eSAobnVtYmVyIG9mIHBlb3BsZSBwZXIga2lsb21ldGVyIHNxdWFyZWQgYXJlYSBvZiB6Y3RhKQoqKm5vaHMqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciBpcyB0aGF0ICoqZG8gbm90IGhhdmUgYSBoaWdoIHNjaG9vbCBkZWdyZWUqKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzCioqc29tZWhzKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgKipzb21lIGhpZ2ggc2Nob29sIGVkdWNhdGlvbioqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMKKipocyoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGNvbXBsZXRpbmcgYSAqKmhpZ2ggc2Nob29sIGRlZ3JlZSoqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgIAoqKnNvbWVjb2xsZWdlKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgY29tcGxldGluZyAqKnNvbWUgY29sbGVnZSBlZHVjYXRpb24qKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzIAoqKmFzc29jaWF0ZSoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGNvbXBsZXRpbmcgYW4gKiphc3NvY2lhdGUgZGVncmVlKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyAKKipiYWNoZWxvcioqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGEgKipiYWNoZWxvcidzIGRlZ3JlZSoqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgCioqZ3JhZCoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGEgKipncmFkdWF0ZSBkZWdyZWUqKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzIAoqKnBvdioqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIGlzIHRoYXQgbGl2ZWQgaW4gWyoqcG92ZXJ0eSoqXShodHRwczovL2FzcGUuaGhzLmdvdi8yMDA4LWhocy1wb3ZlcnR5LWd1aWRlbGluZXMpIGluIDIwMDggLSBvciB3b3VsZCBpdCBoYXZlIGJlZW4gMjAwNyBndWlkZWxpbmVzPz9odHRwczovL2FzcGUuaGhzLmdvdi8yMDA3LWhocy1wb3ZlcnR5LWd1aWRlbGluZXMgPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyAgCioqaHNfb3JsZXNzKiogfCAgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGEgKipoaWdoIHNjaG9vbCBkZWdyZWUgb3IgbGVzcyoqIChzdW0gb2Ygbm9ocywgc29tZWhzLCBhbmQgaHMpICAKKip1cmMyMDEzKiogfCBbMjAxMyBVcmJhbi1ydXJhbCBjbGFzc2lmaWNhdGlvbl0oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2RhdGEvc2VyaWVzL3NyXzAyL3NyMDJfMTY2LnBkZil7dGFyZ2V0PSJfYmxhbmsifSBvZiB0aGUgY291bnR5IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQgPGJyPiAtLSA2IGNhdGVnb3J5IHZhcmlhYmxlIC0gMSBpcyB0b3RhbGx5IHVyYmFuIDYgaXMgY29tcGxldGVseSBydXJhbCA8YnI+ICAtLSBEYXRhIGZyb20gdGhlIFtOYXRpb25hbCBDZW50ZXIgZm9yIEhlYWx0aCBTdGF0aXN0aWNzXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvaW5kZXguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAKKip1cmMyMDA2KiogfCBbMjAwNiBVcmJhbi1ydXJhbCBjbGFzc2lmaWNhdGlvbl0oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2RhdGEvc2VyaWVzL3NyXzAyL3NyMDJfMTU0LnBkZil7dGFyZ2V0PSJfYmxhbmsifSBvZiB0aGUgY291bnR5IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQgPGJyPiAtLSA2IGNhdGVnb3J5IHZhcmlhYmxlIC0gMSBpcyB0b3RhbGx5IHVyYmFuIDYgaXMgY29tcGxldGVseSBydXJhbCA8YnI+IC0tIERhdGEgZnJvbSB0aGUgW05hdGlvbmFsIENlbnRlciBmb3IgSGVhbHRoIFN0YXRpc3RpY3NdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9pbmRleC5odG0pe3RhcmdldD0iX2JsYW5rIn0gICAgIAoqKmFvZCoqIHwgQWVyb3NvbCBPcHRpY2FsIERlcHRoIG1lYXN1cmVtZW50IGZyb20gYSBOQVNBIHNhdGVsbGl0ZSA8YnI+IC0tIGJhc2VkIG9uIHRoZSBkaWZmcmFjdGlvbiBvZiBhIGxhc2VyIDxicj4gLS0gdXNlZCBhcyBhIHByb3h5IG9mIHBhcnRpY3VsYXRlIHBvbGx1dGlvbiA8YnI+IC0tIHVuaXQtbGVzcyAtIGhpZ2hlciB2YWx1ZSBpbmRpY2F0ZXMgbW9yZSBwb2xsdXRpb24gPGJyPiAtLSBEYXRhIGZyb20gTkFTQSAgCgo8L2RldGFpbHM+CgpNYW55IG9mIHRoZXNlIGZlYXR1cmVzIGhhdmUgdG8gZG8gd2l0aCB0aGUgY2lyY3VsYXIgYXJlYSBhcm91bmQgdGhlIG1vbml0b3IgY2FsbGVkIHRoZSAiYnVmZmVyIi4gVGhlc2UgYXJlIGlsbHVzdHJhdGVkIGluIHRoZSBmb2xsb3dpbmcgZmlndXJlOgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjgwMHB4Iix9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJyZWdyZXNzaW9uLnBuZyIpKQpgYGAKCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMTUyOTI5MDYpe3RhcmdldD0iX2JsYW5rIn0KCgoKIyAqKkRhdGEgSW1wb3J0KioKKioqCgpBbGwgb2Ygb3VyIGRhdGEgd2FzIHByZXZpb3VzbHkgY29sbGVjdGVkIGJ5IGEgW3Jlc2VhcmNoZXJdKGh0dHA6Ly93d3cuYmlvc3RhdC5qaHNwaC5lZHUvfnJwZW5nLykgYXQgdGhlIFtKb2hucyBIb3BraW5zIFNjaG9vbCBvZiBQdWJsaWMgSGVhbHRoXShodHRwczovL3d3dy5qaHNwaC5lZHUvKSB3aG8gc3R1ZGllcyBhaXIgcG9sbHV0aW9uIGFuZCBjbGltYXRlIGNoYW5nZS4gCgpXZSBoYXZlIG9uZSBDU1YgZmlsZSB0aGF0IGNvbnRhaW5zIGJvdGggb3VyIHNpbmdsZSAqKm91dGNvbWUgdmFyaWFibGUqKiBhbmQgYWxsIG9mIG91ciAqKmZlYXR1cmVzKiogKG9yIHByZWRpY3RvciB2YXJpYWJsZXMpLgoKTmV4dCwgd2UgaW1wb3J0IG91ciBkYXRhIGludG8gUiBub3cgc28gdGhhdCB3ZSBjYW4gZXhwbG9yZSB0aGUgZGF0YSBmdXJ0aGVyLiAKV2Ugd2lsbCBjYWxsIG91ciBkYXRhIG9iamVjdCBgcG1gIGZvciBwYXJ0aWN1bGF0ZSBtYXR0ZXIuIApXZSBpbXBvcnQgdGhlIGRhdGEgdXNpbmcgdGhlIGByZWFkX2NzdigpYCBmdW5jdGlvbiBmcm9tIHRoZSBgcmVhZHJgIHBhY2thZ2UuIApgYGB7cn0KcG0gPC0gcmVhZHI6OnJlYWRfY3N2KGhlcmUoImRvY3MiLCAicG0yNV9kYXRhLmNzdiIpKQpgYGAKCgoKIyAqKkRhdGEgRXhwbG9yYXRpb24gYW5kIFdyYW5nbGluZyoqCioqKgoKVGhlIGZpcnN0IHN0ZXAgaW4gcGVyZm9ybWluZyBhbnkgZGF0YSBhbmFseXNpcyBpcyB0byBleHBsb3JlIHRoZSBkYXRhLiAKCkZvciBleGFtcGxlLCB3ZSBtaWdodCB3YW50IHRvIGJldHRlciB1bmRlcnN0YW5kIHRoZSB2YXJpYWJsZXMgaW5jbHVkZWQgaW4gdGhlIGRhdGEsIGFzIHdlIG1heSBsZWFybiBhYm91dCBpbXBvcnRhbnQgZGV0YWlscyBhYm91dCB0aGUgZGF0YSB0aGF0IHdlIHNob3VsZCBrZWVwIGluIG1pbmQgYXMgd2UgdHJ5IHRvIHByZWRpY3Qgb3VyIG91dGNvbWUgdmFyaWFibGUuCgpGaXJzdCwgbGV0J3MganVzdCBnZXQgYSBnZW5lcmFsIHNlbnNlIG9mIG91ciBkYXRhLiAKV2UgY2FuIGRvIHRoYXQgdXNpbmcgdGhlIGBnbGltcHNlKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgKGl0IGlzIGFsc28gaW4gdGhlIGB0aWJibGVgIHBhY2thZ2UpLgoKV2Ugd2lsbCBhbHNvIHVzZSB0aGUgYCU+JWAgcGlwZSwgd2hpY2ggY2FuIGJlIHVzZWQgdG8gZGVmaW5lIHRoZSBpbnB1dCBmb3IgbGF0ZXIgc2VxdWVudGlhbCBzdGVwcy4gCgpUaGlzIHdpbGwgbWFrZSBtb3JlIHNlbnNlIHdoZW4gd2UgaGF2ZSBtdWx0aXBsZSBzZXF1ZW50aWFsIHN0ZXBzIHVzaW5nIHRoZSBzYW1lIGRhdGEgb2JqZWN0LiAKClRvIHVzZSB0aGUgcGlwZSBub3RhdGlvbiB3ZSBuZWVkIHRvIGluc3RhbGwgYW5kIGxvYWQgYGRwbHlyYCBhcyB3ZWxsLgoKRm9yIGV4YW1wbGUsIGhlcmUgd2Ugc3RhcnQgd2l0aCBgcG1gIGRhdGEgb2JqZWN0IGFuZCAicGlwZSIgdGhlIG9iamVjdCBpbnRvIGFzIGlucHV0IGludG8gdGhlIGBnbGltcHNlKClgIGZ1bmN0aW9uLiAKVGhlIG91dHB1dCBpcyBpcyBhbiBvdmVydmlldyBvZiB3aGF0IGlzIGluIHRoZSBgcG1gIG9iamVjdCBzdWNoIGFzIHRoZSBudW1iZXIgb2Ygcm93cyBhbmQgY29sdW1ucywgYWxsIHRoZSBjb2x1bW4gbmFtZXMsIHRoZSBkYXRhIHR5cGVzIGZvciBlYWNoIGNvbHVtbiBhbmQgdGhlIGZpcnN0IHZpZXcgdmFsdWVzIGluIGVhY2ggY29sdW1uLiAKVGhlIG91dHB1dCBiZWxvdyBpcyBzY3JvbGxhYmxlIHNvIHlvdSBjYW4gc2VlIGV2ZXJ5dGhpbmcgZnJvbSB0aGUgYGdsaW1wc2UoKWAgZnVuY3Rpb24uIAoKIyMjIyB7LnNjcm9sbGFibGUgfQoKYGBge3J9CiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKcG0gJT4lCiAgZHBseXI6OmdsaW1wc2UoKQpgYGAKCiMjIyMKCldlIGNhbiBzZWUgdGhhdCB0aGVyZSBhcmUgODc2IG1vbml0b3JzIChyb3dzKSBhbmQgdGhhdCB3ZSBoYXZlIDUwIHRvdGFsIHZhcmlhYmxlcyAoY29sdW1ucykgLSBvbmUgb2Ygd2hpY2ggaXMgdGhlIG91dGNvbWUgdmFyaWFibGUuIEluIHRoaXMgY2FzZSwgdGhlIG91dGNvbWUgdmFyaWFibGUgaXMgY2FsbGVkIGB2YWx1ZWAuIAoKTm90aWNlIHRoYXQgc29tZSBvZiB0aGUgdmFyaWFibGVzIHRoYXQgd2Ugd291bGQgdGhpbmsgb2YgYXMgZmFjdG9ycyAob3IgY2F0ZWdvcmljYWwgZGF0YSkgYXJlIGN1cnJlbnRseSBvZiBjbGFzcyBjaGFyYWN0ZXIgYXMgaW5kaWNhdGVkIGJ5IHRoZSBgPGNocj5gIGp1c3QgdG8gdGhlIHJpZ2h0IG9mIHRoZSBjb2x1bW4gbmFtZXMvdmFyaWFibGUgbmFtZXMgaW4gdGhlIGBnbGltcHNlKClgIG91dHB1dC4gVGhpcyBtZWFucyB0aGF0IHRoZSB2YXJpYWJsZSB2YWx1ZXMgYXJlIGNoYXJhY3RlciBzdHJpbmdzLCBzdWNoIGFzIHdvcmRzIG9yIHBocmFzZXMuIAoKVGhlIG90aGVyIHZhcmlhYmxlcyBhcmUgb2YgY2xhc3MgYDxkYmw+YCwgd2hpY2ggc3RhbmRzIGZvciBkb3VibGUgcHJlY2lzaW9uIHdoaWNoIGluZGljYXRlcyB0aGF0IHRoZSBhcmUgbnVtZXJpYyBhbmQgdGhhdCB0aGV5IGhhdmUgZGVjaW1hbCB2YWx1ZXMuIEluIGNvbnRyYXN0LCBvbmUgY291bGQgaGF2ZSBpbnRlZ2VyIHZhbHVlcyB3aGljaCB3b3VsZCBub3QgYWxsb3cgZm9yIGRlY2ltYWwgbnVtYmVycy4gSGVyZSBpcyBhIFtsaW5rXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Eb3VibGUtcHJlY2lzaW9uX2Zsb2F0aW5nLXBvaW50X2Zvcm1hdCl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgbW9yZSBpbmZvcm1hdGlvbiBvbiBkb3VibGUgcHJlY2lzaW9uIG51bWVyaWMgdmFsdWVzLgoKQW5vdGhlciBjb21tb24gZGF0YSBjbGFzcyBpcyBmYWN0b3Igd2hpY2ggaXMgYWJicmV2aWF0ZWQgbGlrZSB0aGlzOiBgPGZjdD5gLiBBIGZhY3RvciBpcyBzb21ldGhpbmcgdGhhdCBoYXMgdW5pcXVlIGxldmVscyBidXQgdGhlcmUgaXMgbm8gYXBwcmVjaWFibGUgb3JkZXIgdG8gdGhlIGxldmVscy4gRm9yIGV4YW1wbGUgd2UgY2FuIGhhdmUgYSBudW1lcmljIHZhbHVlIHRoYXQgaXMganVzdCBhbiBpZCB0aGF0IHdlIHdhbnQgdG8gYmUgaW50ZXJwcmV0ZWQgYXMganVzdCBhIHVuaXF1ZSBsZXZlbCBhbmQgbm90IGFzIHRoZSBudW1iZXIgdGhhdCBpdCB3b3VsZCB0eXBpY2FsbHkgaW5kaWNhdGUuIFRoaXMgd291bGQgYmUgdXNlZnVsIGZvciBzZXZlcmFsIG9mIG91ciB2YXJpYWJsZXM6CgoxLiB0aGUgbW9uaXRvciBJRCAoYGlkYCkKMi4gdGhlIEZlZGVyYWwgSW5mb3JtYXRpb24gUHJvY2Vzc2luZyBTdGFuZGFyZCBudW1iZXIgZm9yIHRoZSBjb3VudHkgd2hlcmUgdGhlIG1vbml0b3Igd2FzIGxvY2F0ZWQgKGBmaXBzYCkKMy4gdGhlIHppcCBjb2RlIHRhYnVsYXRpb24gYXJlYSAoYHpjdGFgKQoKTm9uZSBvZiB0aGUgdmFsdWVzIGFjdHVhbGx5IGhhdmUgYW55IHJlYWwgbnVtZXJpYyBtZWFuaW5nLCBzbyB3ZSB3YW50IHRvIG1ha2Ugc3VyZSB0aGF0IFIgZG9lcyBub3QgaW50ZXJwcmV0IHRoZW0gYXMgaWYgdGhleSBkby4gCgpTbyBsZXQncyBjb252ZXJ0IHRoZXNlIHZhcmlhYmxlcyBpbnRvIGZhY3RvcnMuIApXZSBjYW4gZG8gdGhpcyB1c2luZyB0aGUgYGFjcm9zcygpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIGFuZCB0aGUgYGFzLmZhY3RvcigpYCBiYXNlIGZ1bmN0aW9uLiAKVGhlIGBhY3Jvc3MoKWAgZnVuY3Rpb24gaGFzIHR3byBtYWluIGFyZ3VtZW50czogKGkpIHRoZSBjb2x1bW5zIHlvdSB3YW50IHRvIG9wZXJhdGUgb24gYW5kIChpaSkgdGhlIGZ1bmN0aW9uIG9yIGxpc3Qgb2YgZnVuY3Rpb25zIHRvIGFwcGx5IHRvIGVhY2ggY29sdW1uLiAKCkluIHRoaXMgY2FzZSwgd2UgYXJlIGFsc28gdXNpbmcgdGhlIGBtYWdyaXR0cmAgYXNzaWdubWVudCBwaXBlIG9yIGRvdWJsZSBwaXBlIHRoYXQgbG9va3MgbGlrZSB0aGlzIGAlPD4lYCBvZiB0aGUgYG1hZ3JpdHRyYCBwYWNrYWdlLiAKVGhpcyBhbGxvd3MgdXMgdXNlIHRoZSBgcG1gIGRhdGEgYXMgaW5wdXQsIGJ1dCBhbHNvIHJlYXNzaWducyB0aGUgb3V0cHV0IHRvIHRoZSBzYW1lIGRhdGEgb2JqZWN0IG5hbWUuCgojIyMjIHsuc2Nyb2xsYWJsZSB9CgpgYGB7cn0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpwbSAlPD4lCiAgbXV0YXRlKGFjcm9zcyhjKGlkLCBmaXBzLCB6Y3RhKSwgYXMuZmFjdG9yKSkgCgpnbGltcHNlKHBtKQpgYGAKCiMjIyMKCkdyZWF0ISBOb3cgd2UgY2FuIHNlZSB0aGF0IHRoZXNlIHZhcmlhYmxlcyBhcmUgbm93IGZhY3RvcnMgYXMgaW5kaWNhdGVkIGJ5IGA8ZmN0PmAgYWZ0ZXIgdGhlIHZhcmlhYmxlIG5hbWUuCgoKCiMjIyBTa2ltIHBhY2thZ2UKClRoZSBgc2tpbSgpYCBmdW5jdGlvbiBvZiB0aGUgYHNraW1yYCBwYWNrYWdlIGlzIGFsc28gcmVhbGx5IGhlbHBmdWwgZm9yIGdldHRpbmcgYSBnZW5lcmFsIHNlbnNlIG9mIHlvdXIgZGF0YS4KQnkgZGVzaWduLCBpdCBwcm92aWRlcyBzdW1tYXJ5IHN0YXRpc3RpY3MgYWJvdXQgdmFyaWFibGVzIGluIHRoZSBkYXRhIHNldC4gCgoKIyMjIyB7LnNjcm9sbGFibGUgfQoKYGBge3J9CiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKc2tpbXI6OnNraW0ocG0pCmBgYAoKIyMjIwoKTm90aWNlIGhvdyB0aGVyZSBpcyBhIGNvbHVtbiBjYWxsZWQgYG5fbWlzc2luZ2AgYWJvdXQgdGhlIG51bWJlciBvZiB2YWx1ZXMgdGhhdCBhcmUgbWlzc2luZy4gCgpUaGlzIGlzIGFsc28gaW5kaWNhdGVkIGJ5IHRoZSBgY29tcGxldGVfcmF0ZWAgdmFyaWFibGUgKG9yIG1pc3NpbmcvbnVtYmVyIG9mIG9ic2VydmF0aW9ucykuIAoKSW4gb3VyIGRhdGEgc2V0LCBpdCBsb29rcyBsaWtlIG91ciBkYXRhIGRvIG5vdCBjb250YWluIGFueSBtaXNzaW5nIGRhdGEuIAoKQWxzbyBub3RpY2UgaG93IHRoZSBmdW5jdGlvbiBwcm92aWRlcyBzZXBhcmF0ZSB0YWJsZXMgb2Ygc3VtbWFyeSBzdGF0aXN0aWNzIGZvciBlYWNoIGRhdGEgdHlwZTogY2hhcmFjdGVyLCBmYWN0b3IgYW5kIG51bWVyaWMuIAoKTmV4dCwgdGhlIGBuX3VucWl1ZWAgY29sdW1uIHNob3dzIHVzIHRoZSBudW1iZXIgb2YgdW5pcXVlIHZhbHVlcyBmb3IgZWFjaCBvZiBvdXIgY29sdW1ucy4gCldlIGNhbiBzZWUgdGhhdCB0aGVyZSBhcmUgNDkgc3RhdGVzIHJlcHJlc2VudGVkIGluIHRoZSBkYXRhLgoKV2UgY2FuIHNlZSB0aGF0IGZvciBtYW55IHZhcmlhYmxlcyB0aGVyZSBhcmUgbWFueSBsb3cgdmFsdWVzIGFzIHRoZSBkaXN0cmlidXRpb24gc2hvd3MgdHdvIHBlYWtzLCBvbmUgbmVhciB6ZXJvIGFuZCBhbm90aGVyIHdpdGggYSBoaWdoZXIgdmFsdWUuIAoKVGhpcyBpcyB0cnVlIGZvciB0aGUgYGltcGAgdmFyaWFibGVzIChtZWFzdXJlcyBvZiBkZXZlbG9wbWVudCksIHRoZSBgbmVpYCB2YXJpYWJsZXMgKG1lYXN1cmVzIG9mIGVtaXNzaW9uIHNvdXJjZXMpIGFuZCB0aGUgcm9hZCBkZW5zaXR5IHZhcmlhYmxlcy4gCgpXZSBjYW4gYWxzbyBzZWUgdGhhdCB0aGUgcmFuZ2Ugb2Ygc29tZSBvZiB0aGUgdmFyaWFibGVzIGlzIHZlcnkgbGFyZ2UsIGluIHBhcnRpY3VsYXIgdGhlIGFyZWEgYW5kIHBvcHVsYXRpb24gcmVsYXRlZCB2YXJpYWJsZXMuCgoKTGV0J3MgdGFrZSBhIGxvb2sgdG8gc2VlIHdoaWNoIHN0YXRlcyBhcmUgaW5jbHVkZWQgdXNpbmcgdGhlIGBkaXN0aW5jdCgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlOgoKYGBge3IsIGV2YWwgPSBGQUxTRX0gCnBtICU+JSAKICBkcGx5cjo6ZGlzdGluY3Qoc3RhdGUpIApgYGAKCgpTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0OgoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7ciwgZWNobyA9IEZBTFNFfQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhCnBtICU+JSAKICBkaXN0aW5jdChzdGF0ZSkgJT4lCiMgdGhpcyBhbGxvd3MgdXMgdG8gc2hvdyB0aGUgZnVsbCBvdXRwdXQgaW4gdGhlIHJlbmRlcmVkIHJtYXJrZG93bgogcHJpbnQobiA9IDFlMykKYGBgCiMjIyMKCkl0IGxvb2tzIGxpa2UgIkRpc3RyaWN0IG9mIENvbHVtYmlhIiBpcyBiZWluZyBpbmNsdWRlZCBhcyBhIHN0YXRlLiAKV2UgY2FuIHNlZSB0aGF0IEFsYXNrYSBhbmQgSGF3YWlpIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIGRhdGEuCgpMZXQncyBhbHNvIHRha2UgYSBsb29rIHRvIHNlZSBob3cgbWFueSBtb25pdG9ycyB0aGVyZSBhcmUgaW4gYSBmZXcgY2l0aWVzLiBXZSBjYW4gdXNlIHRoZSBgZmlsdGVyKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gZG8gc28uIEZvciBleGFtcGxlLCBsZXQncyBsb29rIGF0IEFsYnVxdWVycXVlLCBOZXcgTWV4aWNvLiAKCmBgYHtyfQpwbSAlPiUgZHBseXI6OmZpbHRlcihjaXR5ID09ICJBbGJ1cXVlcnF1ZSIpCgpgYGAKCldlIGNhbiBzZWUgdGhhdCB0aGVyZSB3ZXJlIG9ubHkgdHdvIG1vbml0b3JzIGluIHRoZSBjaXR5IG9mIEFsYnVxdWVycXVlIGluIDIwMDYuIExldCdzIGNvbXBhcmUgdGhpcyB3aXRoIEJhbHRpbW9yZS4KCmBgYHtyfQpwbSAlPiUgZHBseXI6OmZpbHRlcihjaXR5ID09ICJCYWx0aW1vcmUiKQoKYGBgCgpUaGVyZSB3ZXJlIGluIGNvbnRyYXN0IGZpdmUgbW9uaXRvcnMgZm9yIHRoZSBjaXR5IG9mIEJhbHRpbW9yZSwgZGVzcGl0ZSB0aGUgZmFjdCB0aGF0IGlmIHdlIHRha2UgYSBsb29rIGF0IHRoZSBsYW5kIGFyZWEgYW5kIHBvcHVsYXRpb24gb2YgdGhlIGNvdW50aWVzIGZvciBCbGF0aW1vcmUgQ2l0eSBhbmQgQWxidXF1ZXJxdWUsIHdlIGNhbiBzZWUgdGhhdCB0aGV5IGhhZCB2ZXJ5IHNpbWlsYXIgbGFuZCBhcmVhIGFuZCBwb3B1bGF0aW9ucy4KCmBgYHtyfQpwbSAlPiUgCiAgZHBseXI6OmZpbHRlcihjaXR5ID09ICJCYWx0aW1vcmUiKSAlPiUgCiAgc2VsZWN0KGNvdW50eV9hcmVhOmNvdW50eV9wb3ApCnBtICU+JSAKICBkcGx5cjo6ZmlsdGVyKGNpdHkgPT0gIkFsYnVxdWVycXVlIikgJT4lCiAgc2VsZWN0KGNvdW50eV9hcmVhOmNvdW50eV9wb3ApCgpgYGAKCkluIGZhY3QsIHRoZSBjb3VudHkgY29udGFpbmluZyBBbGJ1ZXJxdWUgaGFkIGEgbGFyZ2VyIHBvcHVsYXRpb24uIFRodXMgdGhlIG1lYXN1cmVtZW50cyBmb3IgQWxidXF1ZXJxdWUgd2VyZSBub3QgYXMgdGhvcm91Z2ggYXMgdGhleSB3ZXJlIGZvciBCYWx0aW1vcmUuCgpUaGlzIG1heSBiZSBkdWUgdG8gdGhlIGZhY3QgdGhhdCB0aGUgbW9uaXRvciB2YWx1ZXMgd2VyZSBsb3dlciBpbiBBbGJ1cXVlcnF1ZS4gSXQgaXMgaW50ZXJlc3RpbmcgdG8gbm90ZSBoZXJlIHRoYXQgdGhlIENNQVEgdmFsdWVzIGFyZSBxdWl0ZSBzaW1pbGFyIGZvciBib3RoIGNpdGllcy4KCgojIyBFdmFsdWF0ZSBjb3JyZWxhdGlvbgoKSW4gcHJlZGljdGlvbiBhbmFseXNlcywgaXQgaXMgYWxzbyB1c2VmdWwgdG8gZXZhbHVhdGUgaWYgYW55IG9mIHRoZSB2YXJpYWJsZXMgYXJlIGNvcnJlbGF0ZWQuIFdoeSBzaG91bGQgd2UgY2FyZSBhYm91dCB0aGlzPwoKSWYgd2UgYXJlIHVzaW5nIGEgbGluZWFyIHJlZ3Jlc3Npb24gdG8gbW9kZWwgb3VyIGRhdGEgdGhlbiB3ZSBtaWdodCBydW4gaW50byBhIHByb2JsZW0gY2FsbGVkIG11bHRpY29saW5lYXJpdHkgd2hpY2ggY2FuIGxlYWQgdXMgdG8gbWlzaW50ZXJwcmV0IHdoYXQgaXMgcmVhbGx5IHByZWRpY3RpdmUgb2Ygb3VyIG91dGNvbWUgdmFyaWFibGUuIFRoaXMgcGhlbm9tZW5vbiBvY2N1cnMgd2hlbiB0aGUgcHJlZGljdG9yIHZhcmlhYmxlcyBhY3R1YWxseSBwcmVkaWN0IG9uZSBhbm90aGVyLiBTZWUgW3RoaXMgY2FzZSBzdHVkeV0oaHR0cHM6Ly9vcGVuY2FzZXN0dWRpZXMuZ2l0aHViLmlvL29jcy1icC1SVEMtYW5hbHlzaXMvKSBmb3IgYSBkZWVwZXIgZXhwbGFuYXRpb24gYWJvdXQgdGhpcy4gCgpBbm90aGVyIHJlYXNvbiB3ZSBzaG91bGQgbG9vayBvdXQgZm9yIGNvcnJlbGF0aW9uIGlzIHRoYXQgd2UgZG9uJ3Qgd2FudCB0byBpbmNsdWRlIHJlZHVuZGFudCB2YXJpYWJsZXMuIFRoaXMgY2FuIGFkZCB1bm5lY2Vzc2FyeSBub2lzZSB0byBvdXIgYWxnb3JpdGhtIGNhdXNpbmcgYSByZWR1Y3Rpb24gaW4gcHJlZGljdGlvbiBhY2N1cmFjeSBhbmQgaXQgY2FuIGNhdXNlIG91ciBhbGdvcml0aG0gdG8gYmUgdW5uZWNlc3NhcmlseSBzbG93ZXIuIEZpbmFsbHksIGl0IGNhbiBhbHNvIG1ha2UgaXQgZGlmZmljdWx0IHRvIGludGVycHJldCB3aGF0IHZhcmlhYmxlcyBhcmUgYWN0dWFsbHkgcHJlZGljdGl2ZS4KCkludHVpdGl2ZWx5IHdlIGNhbiBleHBlY3Qgc29tZSBvZiBvdXIgdmFyaWFibGVzIHRvIGJlIGNvcnJlbGF0ZWQuCgpMZXQncyBmaXJzdCB0YWtlIGEgbG9vayBhdCBhbGwgb2Ygb3VyIG51bWVyaWMgdmFyaWFibGVzIHdpdGggdGhlYGNvcnJwbG90YCBwYWNrYWdlOgpUaGUgYGNvcnJwbG90YCBwYWNrYWdlIGlzIGFub3RoZXIgb3B0aW9uIHRvIGxvb2sgYXQgY29ycmVsYXRpb24gYW1vbmcgcG9zc2libGUgcHJlZGljdG9ycywgYW5kIHBhcnRpY3VsYXJseSB1c2VmdWwgaWYgd2UgaGF2ZSBtYW55IHByZWRpY3RvcnMuIAoKRmlyc3QsIHdlIGNhbGN1bGF0ZSB0aGUgUGVhcnNvbiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMgYmV0d2VlbiBhbGwgZmVhdHVyZXMgcGFpcndpc2UgdXNpbmcgdGhlIGBjb3IoKWAgZnVuY3Rpb24gb2YgdGhlIGBzdGF0c2AgcGFja2FnZSAod2hpY2ggaXMgbG9hZGVkIGF1dG9tYXRpY2FsbHkpLiBUaGVuIHdlIHVzZSB0aGUgYGNvcnJwbG90Ojpjb3JycGxvdCgpYCBmdW5jdGlvbi4gCgpgYGB7cn0KUE1fY29yIDwtIGNvcihwbSAlPiUgZHBseXI6OnNlbGVjdF9pZihpcy5udW1lcmljKSkKY29ycnBsb3Q6OmNvcnJwbG90KFBNX2NvciwgdGwuY2V4ID0gMC41KQpgYGAKVGhlIGB0bC5jZXggPSAwLjVgIGFyZ3VtZW50IGNvbnRyb2xzIHRoZSBzaXplIG9mIHRoZSB0ZXh0IGxhYmVsLiAKCldlIGNhbiBhbHNvIHBsb3QgdGhlIGFic29sdXRlIHZhbHVlIG9mIHRoZSBQZWFyc29uIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50cyB1c2luZyB0aGUgYGFicygpYCBmdW5jdGlvbiBmcm9tIGJhc2UgUiBhbmQgY2hhbmdlIHRoZSBvcmRlciBvZiB0aGUgY29sdW1ucy4gIApgYGB7cn0KY29ycnBsb3QoYWJzKFBNX2NvciksIG9yZGVyID0gImhjbHVzdCIsIHRsLmNleCA9IDAuNSwgY2wubGltID0gYygwLCAxKSkKCmBgYAoKVGhlcmUgYXJlIHNldmVyYWwgb3B0aW9ucyBmb3Igb3JkZXJpbmcgdGhlIHZhcmlhYmxlcy4gU2VlIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvY29ycnBsb3QvdmlnbmV0dGVzL2NvcnJwbG90LWludHJvLmh0bWwpIGZvciBtb3JlIG9wdGlvbnMuIEhlcmUgd2Ugd2lsbCB1c2UgdGhlICJoY2x1c3QiIG9wdGlvbiBmb3Igb3JkZXJpbmcgYnkgW2hpZXJhcmNoaWNhbCBjbHVzdGVyaW5nXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9IaWVyYXJjaGljYWxfY2x1c3RlcmluZykgLSB3aGljaCB3aWxsIG9yZGVyIHRoZSB2YXJpYWJsZXMgYnkgaG93IHNpbWlsYXIgdGhleSBhcmUgdG8gb25lIGFub3RoZXIuCgpUaGUgYGNsLmxpbSA9IGMoMCwgMSlgIGFyZ3VtZW50IGxpbWl0cyB0aGUgY29sb3IgbGFiZWwgdG8gYmUgYmV0d2VlbiAwIGFuZCAxLiAKCgpXZSBjYW4gc2VlIHRoYXQgdGhlIGRldmVsb3BtZW50IHZhcmlhYmxlcyAoYGltcGApIHZhcmlhYmxlcyBhcmUgY29ycmVsYXRlZCB3aXRoIGVhY2ggb3RoZXIgYXMgd2UgbWlnaHQgZXhwZWN0LiAKV2UgYWxzbyBzZWUgdGhhdCB0aGUgcm9hZCBkZW5zaXR5IHZhcmlhYmxlcyBzZWVtIHRvIGJlIGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyLCBhbmQgdGhlIGVtaXNzaW9uIHZhcmlhYmxlcyBzZWVtIHRvIGJlIGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyLiAKCgpBbHNvIG5vdGljZSB0aGF0IG5vbmUgb2YgdGhlIHByZWRpY3RvcnMgYXJlIGhpZ2hseSBjb3JyZWxhdGVkIHdpdGggb3VyIG91dGNvbWUgdmFyaWFibGUgKGB2YWx1ZWApLgoKV2UgY2FuIHRha2UgYWxzbyB0YWtlIGEgY2xvc2VyIGxvb2sgIHVzaW5nIHRoZSBgZ2djb3JyKClgIGZ1bmN0aW9uIGFuZCB0aGUgYGdncGFpcnMoKWAgZnVuY3Rpb24gb2YgdGhlIGBHR2FsbHlgIHBhY2thZ2UuIAoKVG8gc2VsZWN0IG91ciB2YXJpYWJsZXMgb2YgaW50ZXJlc3Qgd2UgY2FuIHVzZSB0aGUgYHNlbGVjdCgpYCBmdW5jdGlvbiB3aXRoIHRoZSBgY29udGFpbnMoKWAgZnVuY3Rpb24gb2YgdGhlIGB0aWR5cmAgcGFja2FnZS4gCgpGaXJzdCBsZXQncyBsb29rIGF0IHRoZSBgaW1wYC9kZXZlbG9wbWVudCB2YXJpYWJsZXMuIApXZSBjYW4gY2hhbmdlIHRoZSBkZWZhdWx0IGNvbG9yIHBhbGV0dGUgKGBwYWxldHRlID0gIlJkQnUiYCkgYW5kIGFkZCBvbiAKY29ycmVsYXRpb24gY29lZmZpY2llbnRzIHRvIHRoZSBwbG90IChgbGFiZWwgPSBUUlVFYCkuCgpgYGB7ciwgb3V0LndpZHRoID0gIjQwMHB4In0Kc2VsZWN0KHBtLCBjb250YWlucygiaW1wIikpICU+JQogIGdnY29ycihwYWxldHRlID0gIlJkQnUiLCBsYWJlbCA9IFRSVUUpCgpzZWxlY3QocG0sIGNvbnRhaW5zKCJpbXAiKSkgJT4lCiAgZ2dwYWlycygpCmBgYAoKCgpJbmRlZWQsIHdlIGNhbiBzZWUgdGhhdCBgaW1wX2ExMDAwYCBhbmQgYGltcF9hNTAwYCBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQsIGFzIHdlbGwgYXMgYGltcF9hMTAwMDBgLCBgaW1wX2ExNTAwMGAuCgpOZXh0LCBsZXQncyB0YWtlIGEgbG9vayBhdCB0aGUgcm9hZCBkZW5zaXR5IGRhdGE6CgpgYGB7ciwgZmlnLndlaWdodD0xMn0Kc2VsZWN0KHBtLCBjb250YWlucygicHJpIikpICU+JQogIGdnY29ycihwYWxldHRlID0gIlJkQnUiLCBoanVzdCA9IC44NSwgc2l6ZSA9IDMsCiAgICAgICBsYXlvdXQuZXhwPTIsIGxhYmVsID0gVFJVRSkKYGBgCgpXZSBjYW4gc2VlIHRoYXQgbWFueSBvZiB0aGUgcm9hZCBkZW5zaXR5IHZhcmlhYmxlcyBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQgd2l0aCBvbmUgYW5vdGhlciwgd2hpbGUgb3RoZXJzIGFyZSBsZXNzIHNvLgoKRmluYWxseSBsZXQncyBsb29rIGF0IHRoZSBlbWlzc2lvbiB2YXJpYWJsZXMuCgpgYGB7cn0Kc2VsZWN0KHBtLCBjb250YWlucygibmVpIikpICU+JQogIGdnY29ycihwYWxldHRlID0gIlJkQnUiLCBoanVzdCA9IC44NSwgc2l6ZSA9IDMsCiAgICAgICBsYXlvdXQuZXhwPTIsIGxhYmVsID0gVFJVRSkKCnNlbGVjdChwbSwgY29udGFpbnMoIm5laSIpKSAlPiUKICBnZ3BhaXJzKCkKYGBgCgpXZSB3b3VsZCBhbHNvIGV4cGVjdCB0aGUgcG9wdWxhdGlvbiBkZW5zaXR5IGRhdGEgbWlnaHQgY29ycmVsYXRlIHdpdGggc29tZSBvZiB0aGVzZSB2YXJpYWJsZXMuIApMZXQncyB0YWtlIGEgbG9vay4KCmBgYHtyfQpwbSAlPiUKc2VsZWN0KGxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xMDAwMCwgcG9wZGVuc19jb3VudHksIAogICAgICAgbG9nX3ByaV9sZW5ndGhfMTAwMDAsIGltcF9hMTAwMDApICU+JQogIGdnY29ycihwYWxldHRlID0gIlJkQnUiLCAgaGp1c3QgPSAuODUsIHNpemUgPSAzLAogICAgICAgbGF5b3V0LmV4cD0yLCBsYWJlbCA9IFRSVUUpCgpwbSAlPiUKc2VsZWN0KGxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xMDAwMCwgcG9wZGVuc19jb3VudHksIAogICAgICAgbG9nX3ByaV9sZW5ndGhfMTAwMDAsIGltcF9hMTAwMDAsIGNvdW50eV9wb3ApICU+JQogIGdncGFpcnMoKQpgYGAKCgpJbnRlcmVzdGluZywgc28gdGhlc2UgdmFyaWFibGVzIGRvbid0IGFwcGVhciB0byBiZSBoaWdobHkgY29ycmVsYXRlZCwgdGhlcmVmb3JlIHdlIG1pZ2h0IG5lZWQgdmFyaWFibGVzIGZyb20gZWFjaCBvZiB0aGUgY2F0ZWdvcmllcyB0byBwcmVkaWN0IG91ciBtb25pdG9yIFBNfjIuNX4gcG9sbHV0aW9uIHZhbHVlcy4KCkJlY2F1c2Ugc29tZSB2YXJpYWJsZXMgaW4gb3VyIGRhdGEgaGF2ZSBleHRyZW1lIHZhbHVlcywgaXQgbWlnaHQgYmUgZ29vZCB0byB0YWtlIGEgbG9nIHRyYW5zZm9ybWF0aW9uLiBUaGlzIGNhbiBhZmZlY3Qgb3VyIGVzdGltYXRlcyBvZiBjb3JyZWxhdGlvbi4gCmBgYHtyfQpwbSAlPiUKICBtdXRhdGUobG9nX3BvcGRlbnNfY291bnR5PSBsb2cocG9wZGVuc19jb3VudHkpKSAlPiUKc2VsZWN0KGxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xMDAwMCwgbG9nX3BvcGRlbnNfY291bnR5LCAKICAgICAgIGxvZ19wcmlfbGVuZ3RoXzEwMDAwLCBpbXBfYTEwMDAwKSAlPiUKICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgIGhqdXN0ID0gLjg1LCBzaXplID0gMywKICAgICAgIGxheW91dC5leHA9MiwgbGFiZWwgPSBUUlVFKQoKcG0gJT4lCiAgbXV0YXRlKGxvZ19wb3BkZW5zX2NvdW50eT0gbG9nKHBvcGRlbnNfY291bnR5KSkgJT4lCiAgbXV0YXRlKGxvZ19wb3BfY291bnR5ID0gbG9nKGNvdW50eV9wb3ApKSAlPiUKc2VsZWN0KGxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xMDAwMCwgbG9nX3BvcGRlbnNfY291bnR5LCAKICAgICAgIGxvZ19wcmlfbGVuZ3RoXzEwMDAwLCBpbXBfYTEwMDAwLCBsb2dfcG9wX2NvdW50eSkgJT4lCiAgZ2dwYWlycygpCmBgYAoKSW5kZWVkIHRoaXMgaW5jcmVhc2VkIHRoZSBjb3JyZWxhdGlvbiwgYnV0IHZhcmlhYmxlcyBmcm9tIGVhY2ggb2YgdGhlc2UgY2F0ZWdvcmllcyBtYXkgc3RpbGwgcHJvdmUgdG8gYmUgdXNlZnVsIGZvciBwcmVkaWN0aW9uLgoKTm93IHRoYXQgd2UgaGF2ZSBhIHNlbnNlIG9mIHdoYXQgb3VyIGRhdGEgYXJlLCB3ZSBjYW4gZ2V0IHN0YXJ0ZWQgd2l0aCBidWlsZGluZyBhIG1hY2hpbmUgbGVhcm5pbmcgbW9kZWwgdG8gcHJlZGljdCBhaXIgcG9sbHV0aW9uLiAKCiMgKipXaGF0IGlzIG1hY2hpbmUgbGVhcm5pbmc/KiogIHsjd2hhdGlzbWx9CioqKgoKWW91IG1heSBoYXZlIGxlYXJuZWQgYWJvdXQgdGhlIGNlbnRyYWwgZG9nbWEgb2Ygc3RhdGlzdGljcyB0aGF0IHlvdSBzYW1wbGUgZnJvbSBhIHBvcHVsYXRpb24uCgohW10oaW1nL2NkaTEucG5nKQoKVGhlbiB5b3UgdXNlIHRoZSBzYW1wbGUgdG8gdHJ5IHRvIGd1ZXNzIHdoYXQgaXMgaGFwcGVuaW5nIGluIHRoZSBwb3B1bGF0aW9uLgoKIVtdKGltZy9jZGkyLnBuZykKCkZvciBwcmVkaWN0aW9uIHdlIGhhdmUgYSBzaW1pbGFyIHNhbXBsaW5nIHByb2JsZW0KCiFbXShpbWcvY2RwMS5wbmcpCgpCdXQgbm93IHdlIGFyZSB0cnlpbmcgdG8gYnVpbGQgYSBydWxlIHRoYXQgY2FuIGJlIHVzZWQgdG8gcHJlZGljdCBhIHNpbmdsZSBvYnNlcnZhdGlvbidzIHZhbHVlIG9mIHNvbWUgY2hhcmFjdGVyaXN0aWMgdXNpbmcgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBvdGhlciBvYnNlcnZhdGlvbnMuIAoKIVtdKGltZy9jZHAyLnBuZykKCkxldCdzIG1ha2UgdGhpcyBtb3JlIGNvbmNyZXRlLgoKSWYgeW91IHJlY2FsbCBmcm9tIHRoZSBbV2hhdCBhcmUgdGhlIGRhdGE/XSgjd2hhdGFyZXRoZWRhdGEpIHNlY3Rpb24gYWJvdmUsIHdoZW4gd2UgYXJlIHVzaW5nIG1hY2hpbmUgbGVhcm5pbmcgZm9yIHByZWRpY3Rpb24sIG91ciBkYXRhIGNvbnNpc3RzIG9mOiAKCjEuIEFuICoqY29udGludW91cyoqIG91dGNvbWUgdmFyaWFibGUgdGhhdCB3ZSB3YW50IHRvIHByZWRpY3QgCjIuIEEgc2V0IG9mIGZlYXR1cmUocykgKG9yIHByZWRpY3RvciB2YXJpYWJsZXMpIHRoYXQgd2UgdXNlIHRvIHByZWRpY3QgdGhlIG91dGNvbWUgdmFyaWFibGUKCldlIHdpbGwgdXNlICRZJCB0byBkZW5vdGUgdGhlIG91dGNvbWUgdmFyaWFibGUgYW5kICRYID0gKFhfMSwgXGRvdHMsIFhfcCkkIHRvIGRlbm90ZSAkcCQgZGlmZmVyZW50IGZlYXR1cmVzIChvciBwcmVkaWN0b3IgdmFyaWFibGVzKS4gCkJlY2F1c2Ugb3VyIG91dGNvbWUgdmFyaWFibGUgaXMgKipjb250aW51b3VzKiogKGFzIG9wcG9zZWQgdG8gY2F0ZWdvcmljYWwpLCB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBhIHBhcnRpY3VsYXIgdHlwZSBvZiBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobS4gCgpPdXIgZ29hbCBpcyB0byBidWlsZCBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtIHRoYXQgdXNlcyB0aGUgZmVhdHVyZXMgJFgkIGFzIGlucHV0IGFuZCBwcmVkaWN0cyBhbiBvdXRjb21lIHZhcmlhYmxlIChvciBhaXIgcG9sbHV0aW9uIGxldmVscykgaW4gdGhlIHNpdHVhdGlvbiB3aGVyZSB3ZSBkbyBub3Qga25vdyB0aGUgb3V0Y29tZSB2YXJpYWJsZS4gCgpUaGUgd2F5IHdlIGRvIHRoaXMgaXMgdG8gdXNlIGRhdGEgd2hlcmUgd2UgaGF2ZSBib3RoIHRoZSBmZWF0dXJlcyAkKFhfMT14XzEsIFxkb3RzIFhfcD14X3ApJCBhbmQgdGhlIGFjdHVhbCBvdXRjb21lICRZJCBkYXRhIHRvIF90cmFpbl8gYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSB0byBwcmVkaWN0IHRoZSBvdXRjb21lLCB3aGljaCB3ZSBjYWxsICRcaGF0e1l9JC4gIAoKV2hlbiB3ZSBzYXkgdHJhaW4gYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSB3ZSBtZWFuIHRoYXQgd2UgZXN0aW1hdGUgYSBmdW5jdGlvbiAkZiQgdGhhdCB1c2VzIHRoZSBwcmVkaWN0b3IgdmFyaWFibGVzICRYJCBhcyBpbnB1dCBvciAkXGhhdHtZfSA9IGYoWCkkLiAKCiMjIE1MIGFzIGFuIG9wdGltaXphdGlvbiBwcm9ibGVtCgpJZiB3ZSBhcmUgZG9pbmcgYSBnb29kIGpvYiwgdGhlbiBvdXIgcHJlZGljdGVkIG91dGNvbWUgJFxoYXR7WX0kIHNob3VsZCBjbG9zZWx5IG1hdGNoIG91ciBhY3R1YWwgb3V0Y29tZSAkWSQgdGhhdCB3ZSBvYnNlcnZlZC4gCgpJbiB0aGlzIHdheSwgd2UgY2FuIHRoaW5rIG9mIG1hY2hpbmUgbGVhcm5pbmcgKE1MKSBhcyBhbiBvcHRpbWl6YXRpb24gcHJvYmxlbSB0aGF0IHRyaWVzIHRvIG1pbmltaXplIHRoZSBkaXN0YW5jZSBiZXR3ZWVuICRcaGF0e1l9ID0gZihYKSQgYW5kICRZJC4gCgokJGQoWSAtIGYoWCkpJCQKVGhlIGNob2ljZSBvZiBkaXN0YW5jZSBtZXRyaWMgJGQoXGNkb3QpJCBjYW4gYmUgdGhlIG1lYW4gb2YgdGhlIGFic29sdXRlIG9yIHNxdWFyZWQgZGlmZmVyZW5jZSBvciBzb21ldGhpbmcgbW9yZSBjb21wbGljYXRlZC4gCgpNdWNoIG9mIHRoZSBmaWVsZHMgb2Ygc3RhdGlzdGljcyBhbmQgY29tcHV0ZXIgc2NpZW5jZSBhcmUgZm9jdXNlZCBvbiBkZWZpbmluZyAkZiQgYW5kICRkJC4KCiMjIFRoZSBwYXJ0cyBvZiBhbiBNTCBwcm9ibGVtCgpUbyBzZXQgdXAgYSBtYWNoaW5lIGxlYXJuaW5nIChNTCkgcHJvYmxlbSwgd2UgbmVlZCBhIGZldyBjb21wb25lbnRzLgpUbyBzb2x2ZSBhIChzdGFuZGFyZCkgbWFjaGluZSBsZWFybmluZyBwcm9ibGVtIHlvdSBuZWVkOiAKCjEuIEEgZGF0YSBzZXQgdG8gdHJhaW4gZnJvbS4gCjIuIEFuIGFsZ29yaXRobSBvciBzZXQgb2YgYWxnb3JpdGhtcyB5b3UgY2FuIHVzZSB0byB0cnkgdmFsdWVzIG9mICRmJAozLiBBIGRpc3RhbmNlIG1ldHJpYyAkZCQgZm9yIG1lYXN1cmluZyBob3cgY2xvc2UgJFkkIGlzIHRvICRcaGF0e1l9JAo0LiBBIGRlZmluaXRpb24gb2Ygd2hhdCBhICJnb29kIiBkaXN0YW5jZSBpcwoKV2hpbGUgZWFjaCBvZiB0aGVzZSBjb21wb25lbnRzIGlzIGEgX3RlY2huaWNhbF8gcHJvYmxlbSwgdGhlcmUgaGFzIGJlZW4gYSB0b24gb2Ygd29yayBhZGRyZXNzaW5nIHRob3NlIHRlY2huaWNhbCBkZXRhaWxzLiBUaGUgbW9zdCBwcmVzc2luZyBvcGVuIGlzc3VlIGluIG1hY2hpbmUgbGVhcm5pbmcgaXMgcmVhbGl6aW5nIHRoYXQgdGhvdWdoIHRoZXNlIGFyZSBfdGVjaG5pY2FsXyBzdGVwcyB0aGV5IGFyZSBub3QgX29iamVjdGl2ZV8gc3RlcHMuIEluIG90aGVyIHdvcmRzLCBob3cgeW91IGNob29zZSB0aGUgZGF0YSwgYWxnb3JpdGhtLCBtZXRyaWMsIGFuZCBkZWZpbml0aW9uIG9mICJnb29kIiBzYXlzIHdoYXQgeW91IHZhbHVlIGFuZCBjYW4gZHJhbWF0aWNhbGx5IGNoYW5nZSB0aGUgcmVzdWx0cy4gQSBjb3VwbGUgb2YgY2FzZXMgd2hlcmUgdGhpcyB3YXMgYSBiaWcgZGVhbCBhcmU6IAoKMS4gW01hY2hpbmUgbGVhcm5pbmcgZm9yIHJlY2lkaXZpc21dKGh0dHBzOi8vd3d3LnByb3B1YmxpY2Eub3JnL2FydGljbGUvbWFjaGluZS1iaWFzLXJpc2stYXNzZXNzbWVudHMtaW4tY3JpbWluYWwtc2VudGVuY2luZykgLSBwZW9wbGUgYnVpbHQgTUwgbW9kZWxzIHRvIHByZWRpY3Qgd2hvIHdvdWxkIHJlLWNvbW1pdCBhIGNyaW1lLiBCdXQgdGhlc2UgcHJlZGljdGlvbnMgd2VyZSBiYXNlZCBvbiBoaXN0b3JpY2FsbHkgYmlhc2VkIGRhdGEgd2hpY2ggbGVkIHRvIGJpYXNlZCBwcmVkaWN0aW9ucyBhYm91dCB3aG8gd291bGQgY29tbWl0IG5ldyBjcmltZXMuIAoyLiBbRGVjaWRpbmcgaG93IHNlbGYgZHJpdmluZyBjYXJzIHNob3VsZCBhY3RdKGh0dHBzOi8vd3d3Lm5hdHVyZS5jb20vYXJ0aWNsZXMvZDQxNTg2LTAxOC0wNzEzNS0wKSAtIHNlbGYgZHJpdmluZyBjYXJzIHdpbGwgaGF2ZSB0byBtYWtlIGRlY2lzaW9ucyBhYm91dCBob3cgdG8gZHJpdmUsIHdobyB0aGV5IG1pZ2h0IGluanVyZSwgYW5kIGhvdyB0byBhdm9pZCBhY2NpZGVudHMuIERlcGVuZGluZyBvbiBvdXIgY2hvaWNlcyBmb3IgJGYkIGFuZCAkZCQgdGhlc2UgbWlnaHQgbGVhZCB0byB3aWxkbHkgZGlmZmVyZW50IGtpbmRzIG9mIHNlbGYgZHJpdmluZyBjYXJzLiBUcnkgb3V0IHRoZSBbbW9yYWxtYWNoaW5lXShodHRwOi8vbW9yYWxtYWNoaW5lLm1pdC5lZHUvKSB0byBzZWUgaG93IHRoaXMgbG9va3MgaW4gcHJhY3RpY2UuIAoKTm93IHRoYXQgd2Uga25vdyBhIGJpdCBtb3JlIGFib3V0IG1hY2hpbmUgbGVhcm5pbmcsIGxldCdzIGJ1aWxkIGEgbW9kZWwgdG8gcHJlZGljdCBhaXIgcG9sbHV0aW9uIGxldmVscyB1c2luZyB0aGUgYHRpZHltb2RlbHNgIGZyYW1ld29yay4gCgojICoqTWFjaGluZSBsZWFybmluZyB3aXRoIGB0aWR5bW9kZWxzYCoqCioqKgpUaGUgZ29hbCBpcyB0byBidWlsZCBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtIHVzZXMgdGhlIGZlYXR1cmVzIGFzIGlucHV0IGFuZCBwcmVkaWN0cyBhIG91dGNvbWUgdmFyaWFibGUgKG9yIGFpciBwb2xsdXRpb24gbGV2ZWxzKSBpbiB0aGUgc2l0dWF0aW9uIHdoZXJlIHdlIGRvIG5vdCBrbm93IHRoZSBvdXRjb21lIHZhcmlhYmxlLiAKClRoZSB3YXkgd2UgZG8gdGhpcyBpcyB0byB1c2UgZGF0YSB3aGVyZSB3ZSBoYXZlIGJvdGggdGhlIGlucHV0IGFuZCBvdXRwdXQgZGF0YSB0byBfdHJhaW5fIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0uIAoKVG8gdHJhaW4gYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSwgd2Ugd2lsbCB1c2UgdGhlIGB0aWR5bW9kZWxzYCBwYWNrYWdlIGVjb3N5c3RlbS4gCgojIyBPdmVydmlldyAKCiMjIyBUaGUgdGlkeW1vZGVscyBlY29zeXN0ZW0KClRvIHBlcmZvcm0gb3VyIGFuYWx5c2lzIHdlIHdpbGwgYmUgdXNpbmcgdGhlIGB0aWR5bW9kZWxzYCBzdWl0ZSBvZiBwYWNrYWdlcy4gCllvdSBtYXkgYmUgZmFtaWxpYXIgd2l0aCB0aGUgb2xkZXIgcGFja2FnZXMgYGNhcmV0YCBvciBgbWxyYCB3aGljaCBhcmUgYWxzbyBmb3IgbWFjaGluZSBsZWFybmluZyBhbmQgbW9kZWxpbmcgYnV0IGFyZSBub3QgYSBwYXJ0IG9mIHRoZSBgdGlkeXZlcnNlYC4gCltNYXggS3Vobl0oaHR0cHM6Ly9yZXNvdXJjZXMucnN0dWRpby5jb20vYXV0aG9ycy9tYXgta3Vobil7dGFyZ2V0PSJfYmxhbmsifSBkZXNjcmliZXMgYHRpZHltb2RlbHNgIGxpa2UgdGhpczoKCj4gIk90aGVyIHBhY2thZ2VzLCBzdWNoIGFzIGNhcmV0IGFuZCBtbHIsIGhlbHAgdG8gc29sdmUgdGhlIFIgbW9kZWwgQVBJIGlzc3VlLiBUaGVzZSBwYWNrYWdlcyBkbyBhIGxvdCBvZiBvdGhlciB0aGluZ3MgdG9vOiBwcmUtcHJvY2Vzc2luZywgbW9kZWwgdHVuaW5nLCByZXNhbXBsaW5nLCBmZWF0dXJlIHNlbGVjdGlvbiwgZW5zZW1ibGluZywgYW5kIHNvIG9uLiBJbiB0aGUgdGlkeXZlcnNlLCB3ZSBzdHJpdmUgdG8gbWFrZSBvdXIgcGFja2FnZXMgbW9kdWxhciBhbmQgcGFyc25pcCBpcyBkZXNpZ25lZCBvbmx5IHRvIHNvbHZlIHRoZSBpbnRlcmZhY2UgaXNzdWUuIEl0IGlzIG5vdCBkZXNpZ25lZCB0byBiZSBhIGRyb3AtaW4gcmVwbGFjZW1lbnQgZm9yIGNhcmV0LgpUaGUgdGlkeW1vZGVscyBwYWNrYWdlIGNvbGxlY3Rpb24sIHdoaWNoIGluY2x1ZGVzIHBhcnNuaXAsIGhhcyBvdGhlciBwYWNrYWdlcyBmb3IgbWFueSBvZiB0aGVzZSB0YXNrcywgYW5kIHRoZXkgYXJlIGRlc2lnbmVkIHRvIHdvcmsgdG9nZXRoZXIuIFdlIGFyZSB3b3JraW5nIHRvd2FyZHMgaGlnaGVyLWxldmVsIEFQSXMgdGhhdCBjYW4gcmVwbGljYXRlIGFuZCBleHRlbmQgd2hhdCB0aGUgY3VycmVudCBtb2RlbCBwYWNrYWdlcyBjYW4gZG8uIgoKVGhlcmUgYXJlIG1hbnkgUiBwYWNrYWdlcyBpbiB0aGUgYHRpZHltb2RlbHNgIGVjb3N5c3RlbSwgd2hpY2ggYXNzaXN0IHdpdGggdmFyaW91cyBzdGVwcyBpbiB0aGUgcHJvY2VzcyBvZiBidWlsZGluZyBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtLiBUaGVzZSBhcmUgdGhlIG1haW4gcGFja2FnZXMsIGJ1dCB0aGVyZSBhcmUgb3RoZXJzLgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJzaW1wbGV0aWR5bW9kZWxzLnBuZyIpKQpgYGAKClRoaXMgaXMgYSBzY2hlbWF0aWMgb2YgaG93IHRoZXNlIHBhY2thZ2VzIHdvcmsgdG9nZXRoZXIgdG8gYnVpbGQgYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobToKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiTWFjaGluZUxlYXJuaW5nLnBuZyIpKQpgYGAKCiMjIyBCZW5lZml0cyBvZiB0aWR5bW9kZWxzICAKClRoZSB0d28gbWFqb3IgYmVuZWZpdHMgb2YgYHRpZHltb2RlbHNgIGFyZTogCgoxLiBTdGFuZGFyZGl6ZWQgd29ya2Zsb3cvZm9ybWF0L25vdGF0aW9uIGFjcm9zcyBkaWZmZXJlbnQgdHlwZXMgb2YgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG1zICAKCkRpZmZlcmVudCBub3RhdGlvbnMgYXJlIHJlcXVpcmVkIGZvciBkaWZmZXJlbnQgYWxnb3JpdGhtcyBhcyB0aGUgYWxnb3JpdGhtcyBoYXZlIGJlZW4gZGV2ZWxvcGVkIGJ5IGRpZmZlcmVudCBwZW9wbGUuIFRoaXMgd291bGQgcmVxdWlyZSB0aGUgcGFpbnN0YWtpbmcgcHJvY2VzcyBvZiByZWZvcm1hdHRpbmcgdGhlIGRhdGEgdG8gYmUgY29tcGF0aWJsZSB3aXRoIGVhY2ggYWxnb3JpdGhtIGlmIG11bHRpcGxlIGFsZ29yaXRobXMgd2VyZSB0ZXN0ZWQuCgoyLiBDYW4gZWFzaWx5IG1vZGlmeSBwcmUtcHJvY2Vzc2luZywgYWxnb3JpdGhtIGNob2ljZSwgYW5kIGh5cGVyLXBhcmFtZXRlciB0dW5pbmcgbWFraW5nIG9wdGltaXphdGlvbiBlYXN5ICAKCk1vZGlmeWluZyBhIHBpZWNlIG9mIHRoZSBvdmVyYWxsIHByb2Nlc3MgaXMgbm93IGVhc2llciB0aGFuIGJlZm9yZSBiZWNhdXNlIG1hbnkgb2YgdGhlIHN0ZXBzIGFyZSBzcGVjaWZpZWQgdXNpbmcgdGhlIGB0aWR5bW9kZWxzYCBwYWNrYWdlcyBpbiBhIGNvbnZlbmllbnQgbWFubmVyLiBUaHVzIHRoZSBlbnRpcmUgcHJvY2VzcyBjYW4gYmUgcmVydW4gYWZ0ZXIgYSBzaW1wbGUgY2hhbmdlIHRvIHByZS1wcm9jZXNzaW5nIHdpdGhvdXQgbXVjaCBkaWZmaWN1bHR5LgoKCgojIyBTcGxpdHRpbmcgdGhlIGRhdGEKClRoZSBmaXJzdCBzdGVwIGFmdGVyIGRhdGEgZXhwbG9yYXRpb24gaW4gbWFjaGluZSBsZWFybmluZyBhbmFseXNpcyBpcyB0byBbc3BsaXQgdGhlIGRhdGFdKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS90cmFpbi12YWxpZGF0aW9uLWFuZC10ZXN0LXNldHMtNzJjYjQwY2JhOWU3KXt0YXJnZXQ9Il9ibGFuayJ9IGludG8gKip0cmFpbmluZyoqIGFuZCAqKnRlc3RpbmcqKiBkYXRhIHNldHMuIAoKVGhlIHRyYWluaW5nIGRhdGEgc2V0IHdpbGwgYmUgdXNlZCB0byBidWlsZCBhbmQgdHVuZSBvdXIgbW9kZWwuIApUaGlzIGlzIHRoZSBkYXRhIHRoYXQgdGhlIG1vZGVsICJsZWFybnMiIG9uLiAKVGhlIHRlc3RpbmcgZGF0YSBzZXQgd2lsbCBiZSB1c2VkIHRvIGV2YWx1YXRlIHRoZSBwZXJmb3JtYW5jZSBvZiBvdXIgbW9kZWwgaW4gYSBtb3JlIGdlbmVyYWxpemFibGUgd2F5LiBXaGF0IGRvIHdlIG1lYW4gYnkgImdlbmVyYWxpemFibGUiPwoKUmVtZW1iZXIgdGhhdCBvdXIgbWFpbiBnb2FsIGlzIHRvIHVzZSBvdXIgbW9kZWwgdG8gYmUgYWJsZSB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24gbGV2ZWxzIGluIGFyZWFzIHdoZXJlIHRoZXJlIGFyZSBubyBncmF2aW1ldHJpYyBtb25pdG9ycy4gCgpUaGVyZWZvcmUsIGlmIG91ciBtb2RlbCBpcyByZWFsbHkgZ29vZCBhdCBwcmVkaWN0aW5nIGFpciBwb2xsdXRpb24gd2l0aCB0aGUgZGF0YSB0aGF0IHdlIHVzZSB0byBidWlsZCBpdCwgaXQgbWlnaHQgbm90IGRvIHRoZSBiZXN0IGpvYiBmb3IgdGhlIGFyZWFzIHdoZXJlIHRoZXJlIGFyZSBmZXcgdG8gbm8gbW9uaXRvcnMuIAoKVGhpcyB3b3VsZCBjYXVzZSB1cyB0byBoYXZlIHJlYWxseSBnb29kIHByZWRpY3Rpb24gYWNjdXJhY3kgYW5kIHdlIG1pZ2h0IGFzc3VtZSB0aGF0IHdlIHdlcmUgZ29pbmcgdG8gZG8gYSBnb29kIGpvYiBlc3RpbWF0aW5nIGFpciBwb2xsdXRpb24gYW55IHRpbWUgd2UgdXNlIG91ciBtb2RlbCwgYnV0IGluIGZhY3QgdGhpcyB3b3VsZCBsaWtlbHkgbm90IGJlIHRoZSBjYXNlLiAKVGhpcyBzaXR1YXRpb24gaXMgd2hhdCB3ZSBjYWxsICoqW292ZXJmaXR0aW5nXShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vdHJhaW4tdGVzdC1zcGxpdC1hbmQtY3Jvc3MtdmFsaWRhdGlvbi1pbi1weXRob24tODBiNjFiZWNhNGI2KXt0YXJnZXQ9Il9ibGFuayJ9ICoqLgoKT3ZlcmZpdHRpbmcgaGFwcGVucyB3aGVuIHdlIGVuZCB1cCBtb2RlbGluZyBub3Qgb25seSB0aGUgbWFqb3IgcmVsYXRpb25zaGlwcyBpbiBvdXIgZGF0YSBidXQgYWxzbyB0aGUgbm9pc2Ugd2l0aGluIG91ciBkYXRhLiAKCmBgYHtyLCBlY2hvPUZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly9taXJvLm1lZGl1bS5jb20vbWF4LzExMTAvMSp0QkVyWFlWdlR3MmpTVVlLN3RoVTJBLnBuZyIpCmBgYAoKIyMjIyMgW1tzb3VyY2VdXShodHRwczovL21pcm8ubWVkaXVtLmNvbS9tYXgvMTExMC8xKnRCRXJYWVZ2VHcyalNVWUs3dGhVMkEucG5nKXt0YXJnZXQ9Il9ibGFuayJ9CgpJZiB3ZSBnZXQgZ29vZCBwcmVkaWN0aW9uIHdpdGggb3VyIHRlc3Rpbmcgc2V0LCB0aGVuIHdlIGtub3cgdGhhdCBvdXIgbW9kZWwgY2FuIGJlIGFwcGxpZWQgdG8gb3RoZXIgZGF0YSBhbmQgd2lsbCBsaWtlbHkgcGVyZm9ybSB3ZWxsLiBXZSB3aWxsIGRpc2N1c3MgdGhpcyBtb3JlIGxhdGVyLgoKV2Ugd2lsbCBub3QgdG91Y2ggdGhlIHRlc3Rpbmcgc2V0IHVudGlsIHdlIGhhdmUgY29tcGxldGVkIG9wdGltaXppbmcgb3VyIG1vZGVsIHdpdGggdGhlIHRyYWluaW5nIHNldC4gClRoaXMgd2lsbCBhbGxvdyB1cyB0byBoYXZlIGEgbGVzcyBiaWFzZWQgZXZhbHVhdGlvbiBvZiBob3cgd2VsbCBvdXIgbW9kZWwgY2FuIGRvIHdpdGggb3RoZXIgZGF0YSBiZXNpZGVzIHRoZSBkYXRhIHVzZWQgaW4gdGhlIHRyYWluaW5nIHNldCB0byBidWlsZCB0aGUgbW9kZWwuIApJZGVhbGx5LCB5b3Ugd291bGQgYWxzbyB3YW50IGEgY29tcGxldGVseSBpbmRlcGVuZGVudCBkYXRhIHNldCB0byBmdXJ0aGVyIHRlc3QgdGhlIHBlcmZvcm1hbmNlIG9mIHlvdXIgbW9kZWwuCgpUbyBzcGxpdCB0aGUgZGF0YSBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nLCB3ZSB3aWxsIHVzZSB0aGUgYGluaXRpYWxfc3BsaXQoKWAgZnVuY3Rpb24gaW4gdGhlIGByc2FtcGxlYCBwYWNrYWdlIHRvIHNwZWNpZnkgaG93IHdlIHdhbnQgdG8gc3BsaXQgb3VyIGRhdGEuCgoKYGBge3IsIGVjaG89RkFMU0V9Cgprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJzcGxpdC5wbmciKSkKYGBgCgpgYGB7cn0Kc2V0LnNlZWQoMTIzNCkKcG1fc3BsaXQgPC0gcnNhbXBsZTo6aW5pdGlhbF9zcGxpdChkYXRhID0gcG0sIHByb3AgPSAyLzMpCnBtX3NwbGl0CmBgYAoKQSBjb3VwbGUgb2Ygbm90ZXMgZnJvbSB0aGUgY29kZSBhYm92ZTogCgotIFR5cGljYWxseSwgZGF0YSBhcmUgc3BsaXQgaW50byAzLzQgb2YgdGhlIG9ic2VydmF0aW9ucyBmb3IgdHJhaW5pbmcgYW5kIDEvNCBmb3IgdGVzdGluZy4gVGhpcyBpcyB0aGUgZGVmYXVsdCBwcm9wb3J0aW9uIGFuZCBkb2VzIG5vdCBuZWVkIHRvIGJlIHNwZWNpZmllZC4gSG93ZXZlciwgeW91IGNhbiBjaGFuZ2UgdGhlIHByb3BvcnRpb24gdXNpbmcgdGhlIGBwcm9wYCBhcmd1bWVudCwgd2hpY2ggd2Ugd2lsbCBkbyB0aGF0IGhlcmUgZm9yIGlsbHVzdHJhdGl2ZSBwdXJwb3Nlcy4KLSBTaW5jZSB0aGUgc3BsaXQgaXMgcGVyZm9ybWVkIHJhbmRvbWx5LCBpdCBpcyBhIGdvb2QgaWRlYSB0byB1c2UgdGhlIGBzZXQuc2VlZCgpYCBmdW5jdGlvbiBpbiBiYXNlIFIgdG8gZW5zdXJlIHRoYXQgaWYgeW91ciByZXJ1biB5b3VyIGNvZGUgdGhhdCB5b3VyIHNwbGl0IHdpbGwgYmUgdGhlIHNhbWUgbmV4dCB0aW1lLgotIFdlIGNhbiBzZWUgdGhlIG51bWJlciBvZiBtb25pdG9ycyBpbiBvdXIgdHJhaW5pbmcsIHRlc3RpbmcsIGFuZCBvcmlnaW5hbCBkYXRhIGJ5IHR5cGluZyBpbiB0aGUgbmFtZSBvZiBvdXIgc3BsaXQgb2JqZWN0LiBUaGUgcmVzdWx0IHdpbGwgbG9vayBsaWtlIHRoaXM6Cjx0cmFpbmluZyBkYXRhIHNhbXBsZSBudW1iZXIsIHRlc3RpbmcgZGF0YSBzYW1wbGUgbnVtYmVyLCBvcmlnaW5hbCBzYW1wbGUgbnVtYmVyPiAKCk5vdywgeW91IGNhbiBhbHNvIHNwZWNpZnkgYSB2YXJpYWJsZSB0byBzdHJhdGlmeSBieSB3aXRoIHRoZSBgc3RyYXRhYCBhcmd1bWVudC4gClRoaXMgaXMgdXNlZnVsIGlmIHlvdSBoYXZlIGltYmFsYW5jZWQgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGFuZCB5b3Ugd291bGQgbGlrZSB0byBpbnRlbnRpb25hbGx5IG1ha2Ugc3VyZSB0aGF0IHRoZXJlIGFyZSBzaW1pbGFyIG51bWJlciBvZiBzYW1wbGVzIG9mIHRoZSByYXJlciBjYXRlZ29yaWVzIGluIGJvdGggdGhlIHRlc3RpbmcgYW5kIHRyYWluaW5nIHNldHMuIApPdGhlcndpc2UgdGhlIHNwbGl0IGlzIHBlcmZvcm1lZCByYW5kb21seS4gCgpBY2NvcmRpbmcgdG8gdGhlIFtkb2N1bWVudGF0aW9uXShodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvcnNhbXBsZS92ZXJzaW9ucy8wLjAuNS90b3BpY3MvaW5pdGlhbF9zcGxpdCkgZm9yIHRoZSBgcnNhbXBsZWAgcGFja2FnZToKCj4gVGhlIHN0cmF0YSBhcmd1bWVudCBjYXVzZXMgdGhlIHJhbmRvbSBzYW1wbGluZyB0byBiZSBjb25kdWN0ZWQgd2l0aGluIHRoZSBzdHJhdGlmaWNhdGlvbiB2YXJpYWJsZS4gVGhpcyBjYW4gaGVscCBlbnN1cmUgdGhhdCB0aGUgbnVtYmVyIG9mIGRhdGEgcG9pbnRzIGluIHRoZSB0cmFpbmluZyBkYXRhIGlzIGVxdWl2YWxlbnQgdG8gdGhlIHByb3BvcnRpb25zIGluIHRoZSBvcmlnaW5hbCBkYXRhIHNldC4KCkluIHRoZSBjYXNlIHdpdGggb3VyIGRhdGEgc2V0LCBwZXJoYXBzIHdlIHdvdWxkIGxpa2Ugb3VyIHRyYWluaW5nIHNldCB0byBoYXZlIHNpbWlsYXIgcHJvcG9ydGlvbnMgb2YgbW9uaXRvcnMgZnJvbSBlYWNoIG9mIHRoZSBzdGF0ZXMgYXMgaW4gdGhlIGluaXRpYWwgZGF0YS4gClRoaXMgbWlnaHQgYmUgdXNlZnVsIGlmIHdlIHdhbnQgb3VyIG1vZGVsIHRvIGJlIGdlbmVyYWxpemFibGUgYWNyb3NzIGFsbCBvZiB0aGUgc3RhdGVzLgoKV2UgY2FuIHNlZSB0aGF0IGluZGVlZCB0aGVyZSBhcmUgZGlmZmVyZW50IHByb3BvcnRpb25zIG9mIG1vbml0b3JzIGluIGVhY2ggc3RhdGUgYnkgdXNpbmcgdGhlIGBjb3VudCgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiAKCmBgYHtyLCBldmFsID0gRkFMU0V9CmNvdW50KHBtLCBzdGF0ZSkKYGBgCgpTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0OgoKIyMjIyB7LnNjcm9sbGFibGUgfQoKYGBge3IsIGVjaG89RkFMU0V9CiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKY291bnQocG0sIHN0YXRlKSAlPiUKICBwcmludChuID0gMWUzKQpgYGAKIyMjIwoKSWYgb3VyIGRhdGEgc2V0IHdlcmUgbGFyZ2UgZW5vdWdoIGl0IG1pZ2h0IGJlIG5pY2UgdGhlbiB0byBzdHJhdGlmeSBieSBzdGF0ZSB1c2luZyB0aGUgYHN0cmF0YSA9ICJzdGF0ZSJgIGFyZ3VtZW50IGluIGBpbml0aWFsX3NwbGl0KClgLCBidXQgb3VyIGRhdGEgaXMgdW5mb3J0dW5hdGVseSBub3QgbGFyZ2UgZW5vdWdoLiAKCkltcG9ydGFudGx5IHRoZSBgaW5pdGlhbF9zcGxpdCgpYCBmdW5jdGlvbiBvbmx5IGRldGVybWluZXMgd2hhdCByb3dzIG9mIG91ciBgcG1gIGRhdGEgZnJhbWUgc2hvdWxkIGJlIGFzc2lnbmVkIGZvciB0cmFpbmluZyBvciB0ZXN0aW5nLCBpdCBkb2VzIG5vdCBhY3R1YWxseSBzcGxpdCB0aGUgZGF0YS4gCgpUbyBleHRyYWN0IHRoZSB0ZXN0aW5nIGFuZCB0cmFpbmluZyBkYXRhIHdlIGNhbiB1c2UgdGhlIGB0cmFpbmluZygpYCBhbmQgYHRlc3RpbmcoKWAgZnVuY3Rpb25zIGFsc28gb2YgdGhlIGByc2FtcGxlYCBwYWNrYWdlLgoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cn0KdHJhaW5fcG0gPC1yc2FtcGxlOjp0cmFpbmluZyhwbV9zcGxpdCkKdGVzdF9wbSA8LXJzYW1wbGU6OnRlc3RpbmcocG1fc3BsaXQpCiAKIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpjb3VudCh0cmFpbl9wbSwgc3RhdGUpCmNvdW50KHRlc3RfcG0sIHN0YXRlKQpgYGAKIyMjIwoKCgojIyBQcmVwYXJpbmcgZm9yIHByZS1wcm9jZXNzaW5nIHRoZSBkYXRhCgpBZnRlciBzcGxpdHRpbmcgdGhlIGRhdGEsIHRoZSBuZXh0IHN0ZXAgaXMgdG8gcHJvY2VzcyB0aGUgdHJhaW5pbmcgYW5kIHRlc3RpbmcgZGF0YSBzbyB0aGF0IHRoZSBkYXRhIGFyZSBhcmUgY29tcGF0aWJsZSBhbmQgb3B0aW1pemVkIHRvIGJlIHVzZWQgd2l0aCB0aGUgbW9kZWwuIApUaGlzIGludm9sdmVzIGFzc2lnbmluZyB2YXJpYWJsZXMgdG8gc3BlY2lmaWMgcm9sZXMgd2l0aGluIHRoZSBtb2RlbCBhbmQgcHJlLXByb2Nlc3NpbmcgbGlrZSBzY2FsaW5nIHZhcmlhYmxlcyBhbmQgcmVtb3ZpbmcgcmVkdW5kYW50IHZhcmlhYmxlcy4gClRoaXMgcHJvY2VzcyBpcyBhbHNvIGNhbGxlZCBmZWF0dXJlIGVuZ2luZWVyaW5nLgoKVG8gZG8gdGhpcyBpbiBgdGlkeW1vZGVsc2AsIHdlIHdpbGwgY3JlYXRlIHdoYXQncyBjYWxsZWQgYSAicmVjaXBlIiB1c2luZyB0aGUgYHJlY2lwZXNgIHBhY2thZ2UsIHdoaWNoIGlzIGEgc3RhbmRhcmRpemVkIGZvcm1hdCBmb3IgYSBzZXF1ZW5jZSBvZiBzdGVwcyBmb3IgcHJlLXByb2Nlc3NpbmcgdGhlIGRhdGEuClRoaXMgY2FuIGJlIHZlcnkgdXNlZnVsIGJlY2F1c2UgaXQgbWFrZXMgdGVzdGluZyBvdXQgZGlmZmVyZW50IHByZS1wcm9jZXNzaW5nIHN0ZXBzIG9yIGRpZmZlcmVudCBhbGdvcml0aG1zIHdpdGggdGhlIHNhbWUgcHJlLXByb2Nlc3NpbmcgdmVyeSBlYXN5IGFuZCByZXByb2R1Y2libGUuCkNyZWF0aW5nIGEgcmVjaXBlIHNwZWNpZmllcyAqKmhvdyBhIGRhdGEgZnJhbWUgb2YgcHJlZGljdG9ycyBzaG91bGQgYmUgY3JlYXRlZCoqIC0gaXQgc3BlY2lmaWVzIHdoYXQgdmFyaWFibGVzIHRvIGJlIHVzZWQgYW5kIHRoZSBwcmUtcHJvY2Vzc2luZyBzdGVwcywgYnV0IGl0ICoqZG9lcyBub3QgZXhlY3V0ZSB0aGVzZSBzdGVwcyoqIG9yIGNyZWF0ZSB0aGUgZGF0YSBmcmFtZSBvZiBwcmVkaWN0b3JzLgoKIyMjIFN0ZXAgMTogU3BlY2lmeSB2YXJpYWJsZXMgcm9sZXMgd2l0aCBgcmVjaXBlKClgIGZ1bmN0aW9uCgpUaGUgZmlyc3QgdGhpbmcgdG8gZG8gdG8gY3JlYXRlIGEgcmVjaXBlIGlzIHRvIHNwZWNpZnkgd2hpY2ggdmFyaWFibGVzIHdlIHdpbGwgYmUgdXNpbmcgYXMgb3VyIG91dGNvbWUgYW5kIHByZWRpY3RvcnMgdXNpbmcgdGhlIGByZWNpcGUoKWAgZnVuY3Rpb24uIApJbiB0ZXJtcyBvZiB0aGUgbWV0YXBob3Igb2YgYmFraW5nLCB3ZSBjYW4gdGhpbmsgb2YgdGhpcyBhcyBsaXN0aW5nIG91ciBpbmdyZWRpZW50cy4gClRyYW5zbGF0aW5nIHRoaXMgdG8gdGhlIGByZWNpcGVzYCBwYWNrYWdlLCB3ZSB1c2UgdGhlIGByZWNpcGUoKWAgZnVuY3Rpb24gdG8gYXNzaWduIHJvbGVzIHRvIGFsbCB0aGUgdmFyaWFibGVzLiAKCkxldCdzIHRyeSB0aGUgc2ltcGxlc3QgcmVjaXBlIHdpdGggbm8gcHJlLXByb2Nlc3Npbmcgc3RlcHM6IHNpbXBseSBsaXN0IHRoZSBvdXRjb21lIGFuZCBwcmVkaWN0b3IgdmFyaWFibGVzLgoKV2UgY2FuIGRvIHNvIGluIHR3byB3YXlzOiAgCgoxKSBVc2luZyBmb3JtdWxhIG5vdGF0aW9uICAKMikgQXNzaWduaW5nIHJvbGVzIHRvIGVhY2ggdmFyaWFibGUgIAoKTGV0J3MgbG9vayBhdCB0aGUgZmlyc3Qgd2F5IHVzaW5nIGZvcm11bGEgbm90YXRpb24sIHdoaWNoIGxvb2tzIGxpa2UgdGhpczogIAoKb3V0Y29tZShzKSB+IHByZWRpY3RvcihzKSAgCgpJZiBpbiB0aGUgY2FzZSBvZiBtdWx0aXBsZSBwcmVkaWN0b3JzIG9yIGEgbXVsdGl2YXJpYXRlIHNpdHVhdGlvbiB3aXRoIHR3byBvdXRjb21lcywgdXNlIGEgcGx1cyBzaWduOiAgCgpvdXRjb21lMSArIG91dGNvbWUyIH4gcHJlZGljdG9yMSArIHByZWRpY3RvcjIgIAoKSWYgd2Ugd2FudCB0byBpbmNsdWRlIGFsbCBwcmVkaWN0b3JzIHdlIGNhbiB1c2UgYSBwZXJpb2QgbGlrZSBzbzogIAoKb3V0Y29tZV92YXJpYWJsZV9uYW1lIH4gLiAgCgpOb3cgd2l0aCBvdXIgZGF0YSwgd2Ugd2lsbCBzdGFydCBieSBtYWtpbmcgYSByZWNpcGUgZm9yIG91ciB0cmFpbmluZyBkYXRhLgpJZiB5b3UgcmVjYWxsLCB0aGUgY29udGludW91cyBvdXRjb21lIHZhcmlhYmxlIGlzIGB2YWx1ZWAgKHRoZSBhdmVyYWdlIGFubnVhbCBncmF2aW1ldHJpYyBtb25pdG9yIFBNfjIuNX4gY29uY2VudHJhdGlvbiBpbiB1Zy9tXjNeKS4gCk91ciBmZWF0dXJlcyAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykgYXJlIGFsbCB0aGUgb3RoZXIgdmFyaWFibGVzIGV4Y2VwdCB0aGUgbW9uaXRvciBJRCwgd2hpY2ggaXMgYW4gYGlkYCB2YXJpYWJsZS4KClRoZSByZWFzb24gbm90IHRvIGluY2x1ZGUgdGhlIGBpZGAgdmFyaWFibGUgaXMgYmVjYXVzZSB0aGlzIHZhcmlhYmxlIGluY2x1ZGVzIHRoZSBjb3VudHkgbnVtYmVyIGFuZCBhIG51bWJlciBkZXNpZ25hdGluZyB3aGljaCBwYXJ0aWN1bGFyIG1vbml0b3IgdGhlIHZhbHVlcyBjYW1lIGZyb20gKG9mIHRoZSBtb25pdG9ycyB0aGVyZSBhcmUgaW4gdGhhdCBjb3VudHkpLiAKU2luY2UgdGhpcyBudW1iZXIgaXMgYXJiaXRyYXJ5IGFuZCB0aGUgY291bnR5IGluZm9ybWF0aW9uIGlzIGFsc28gZ2l2ZW4gaW4gdGhlIGRhdGEsIGFuZCB0aGUgZmFjdCB0aGF0IGVhY2ggbW9uaXRvciBvbmx5IGhhcyBvbmUgdmFsdWUgaW4gdGhlIGB2YWx1ZWAgdmFyaWFibGUsIG5vdGhpbmcgaXMgZ2FpbmVkIGJ5IGluY2x1ZGluZyB0aGlzIHZhcmlhYmxlIGFuZCBpdCBtYXkgaW5zdGVhZCBpbnRyb2R1Y2Ugbm9pc2UuIApIb3dldmVyLCBpdCBpcyB1c2VmdWwgdG8ga2VlcCB0aGlzIGRhdGEgdG8gdGFrZSBhIGxvb2sgYXQgd2hhdCBpcyBoYXBwZW5pbmcgbGF0ZXIuIApXZSB3aWxsIHNob3cgeW91IHdoYXQgdG8gZG8gaW4gdGhpcyBjYXNlIGluIGp1c3QgYSBiaXQuCgpJbiB0aGUgc2ltcGxlc3QgY2FzZSwgd2UgbWlnaHQgdXNlIGFsbCBwcmVkaWN0b3JzIGxpa2UgdGhpczoKCmBgYHtyfQpzaW1wbGVfcmVjIDwtIHRyYWluX3BtICU+JQogIHJlY2lwZXM6OnJlY2lwZSh2YWx1ZSB+IC4pCgpzaW1wbGVfcmVjCmBgYAoKV2Ugc2VlIGEgcmVjaXBlIGhhcyBiZWVuIGNyZWF0ZWQgd2l0aCAxIG91dGNvbWUgdmFyaWFibGUgYW5kIDQ5IHByZWRpY3RvciB2YXJpYWJsZXMgKG9yIGZlYXR1cmVzKS4gCkFsc28sIG5vdGljZSBob3cgd2UgbmFtZWQgdGhlIG91dHB1dCBvZiBgcmVjaXBlKClgLiAKVGhlIG5hbWluZyBjb252ZW50aW9uIGZvciByZWNpcGUgb2JqZWN0cyBpcyBgKl9yZWNgIG9yIGByZWNgLiAKCk5vdywgbGV0J3MgZ2V0IGJhY2sgdG8gdGhlIGBpZGAgdmFyaWFibGUuIApJbnN0ZWFkIG9mIGluY2x1ZGluZyBpdCBhcyBhIHByZWRpY3RvciB2YXJpYWJsZSwgd2UgY291bGQgYWxzbyB1c2UgdGhlIGB1cGRhdGVfcm9sZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UuCgpgYGB7cn0Kc2ltcGxlX3JlYyA8LSB0cmFpbl9wbSAlPiUKICByZWNpcGVzOjpyZWNpcGUodmFsdWUgfiAuKSAlPiUKICByZWNpcGVzOjp1cGRhdGVfcm9sZShpZCwgbmV3X3JvbGUgPSAiaWQgdmFyaWFibGUiKQoKc2ltcGxlX3JlYwpgYGAKCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayBoZXJlIGxlYXJuIG1vcmUgYWJvdXQgdGhlIHdvcmtpbmcgd2l0aCBgaWRgIHZhcmlhYmxlcyA8L3N1bW1hcnk+CgpUaGlzIG9wdGlvbiB3b3JrcyB3ZWxsIHdpdGggdGhlIG5ld2VyIGB3b3JrZmxvd3NgIHBhY2thZ2UsIGhvd2V2ZXIgYGlkYCB2YXJpYWJsZXMgYXJlIG9mdGVuIGRyb3BwZWQgZnJvbSBhbmFseXNlcyB0aGF0IGRvIG5vdCB1c2UgdGhpcyBuZXdlciBwYWNrYWdlIGFzIHRoZXkgY2FuIG1ha2UgdGhlIHByb2Nlc3MgZGlmZmljdWx0IHdpdGggdXNpbmcgdGhlIGBwYXJzbmlwYCBwYWNrYWdlIGFsb25lIGR1ZSB0byB0aGUgZmFjdCB0aGF0IG5ldyBsZXZlbHMgKG9yIHBvc3NpYmxlIHZhbHVlcykgbWF5IGJlIGludHJvZHVjZWQgd2l0aCB0aGUgdGVzdGluZyBkYXRhLgoKPC9kZXRhaWxzPgoKV2UgY291bGQgYWxzbyBzcGVjaWZ5IHRoZSBvdXRjb21lIGFuZCBwcmVkaWN0b3JzIGluIHRoZSBzYW1lIHdheSBhcyB3ZSBqdXN0IHNwZWNpZmllZCB0aGUgaWQgdmFyaWFibGUuIApQbGVhc2Ugc2VlIFtoZXJlXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JlY2lwZXMvcmVmZXJlbmNlL3JlY2lwZS5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBleGFtcGxlcyBvZiBvdGhlciByb2xlcyBmb3IgdmFyaWFibGVzLiAKVGhlIHJvbGUgY2FuIGJlIGFjdHVhbGx5IGJlIGFueSB2YWx1ZS4gCgpUaGUgb3JkZXIgaXMgaW1wb3J0YW50IGhlcmUsIGFzIHdlIGZpcnN0IG1ha2UgYWxsIHZhcmlhYmxlcyBwcmVkaWN0b3JzIGFuZCB0aGVuIG92ZXJyaWRlIHRoaXMgcm9sZSBmb3IgdGhlIG91dGNvbWUgYW5kIGBpZGAgdmFyaWFibGUuIApXZSB3aWxsIHVzZSB0aGUgYGV2ZXJ5dGhpbmcoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSB0byBzdGFydCB3aXRoIGFsbCBvZiB0aGUgdmFyaWFibGVzIGluIGB0cmFpbl9wbWAuCgpgYGB7cn0Kc2ltcGxlX3JlYyA8LXJlY2lwZSh0cmFpbl9wbSkgJT4lCiAgICB1cGRhdGVfcm9sZShldmVyeXRoaW5nKCksIG5ld19yb2xlID0gInByZWRpY3RvciIpJT4lCiAgICB1cGRhdGVfcm9sZSh2YWx1ZSwgbmV3X3JvbGUgPSAib3V0Y29tZSIpJT4lCiAgICB1cGRhdGVfcm9sZShpZCwgbmV3X3JvbGUgPSAiaWQgdmFyaWFibGUiKQoKc2ltcGxlX3JlYwpgYGAKCklmIHdlIHdhbnQgdG8gdGFrZSBhIGxvb2sgYXQgb3VyIGZvcm11bGEgZnJvbSBvdXIgcmVjaXBlLCB3ZSBjYW4gZG8gdXNlIHRoZSBgZm9ybXVsYSgpYCBmdW5jdGlvbiBvZiB0aGUgYHN0YXRzYCBwYWNrYWdlLgoKYGBge3J9CmZvcm11bGEoc2ltcGxlX3JlYykKYGBgCgpXZSBjYW4gYWxzbyB2aWV3IG91ciByZWNpcGUgaW4gbW9yZSBkZXRhaWwgdXNpbmcgdGhlIGJhc2UgYHN1bW1hcnkoKWAgZnVuY3Rpb24uCgpgYGB7cn0Kc3VtbWFyeShzaW1wbGVfcmVjKQpgYGAKClRvIHN1bW1hcml6ZSB0aGlzIHN0ZXAsIHdlIHVzZSB0aGUgYHJlY2lwZSgpYCBmdW5jdGlvbiB0byBhc3NpZ24gcm9sZXMgdG8gYWxsIHRoZSB2YXJpYWJsZXM6IAoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNDAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJTdGFydGluZ19hX3JlY2lwZV9yZWNpcGVzMS5wbmciKSkKYGBgCgoKIyMjIFN0ZXAgMjogU3BlY2lmeSB0aGUgcHJlLXByb2Nlc3Npbmcgc3RlcHMgd2l0aCBgc3RlcCooKWAgZnVuY3Rpb25zCgpOZXh0LCB3ZSB1c2UgdGhlIGBzdGVwKigpYCBmdW5jdGlvbnMgZnJvbSB0aGUgYHJlY2lwZWAgcGFja2FnZSB0byBzcGVjaWZ5IHByZS1wcm9jZXNzaW5nIHN0ZXBzLiAKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjQwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiTWFraW5nX2FfcmVjaXBlX3JlY2lwZXMyLnBuZyIpKQpgYGAKCioqVGhpcyBbbGlua10oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yZWNpcGVzL3JlZmVyZW5jZS9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGFuZCB0aGlzIFtsaW5rXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmVjaXBlcy9yZWNpcGVzLnBkZil7dGFyZ2V0PSJfYmxhbmsifSBzaG93IHRoZSBtYW55IG9wdGlvbnMgZm9yIHJlY2lwZSBzdGVwIGZ1bmN0aW9ucy4qKgoKPHU+VGhlcmUgYXJlIHN0ZXAgZnVuY3Rpb25zIGZvciBhIHZhcmlldHkgb2YgcHVycG9zZXM6PC91PgoKMS4gWyoqSW1wdXRhdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9JbXB1dGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAtLSBmaWxsaW5nIGluIG1pc3NpbmcgdmFsdWVzIGJhc2VkIG9uIHRoZSBleGlzdGluZyBkYXRhIAoyLiBbKipUcmFuc2Zvcm1hdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EYXRhX3RyYW5zZm9ybWF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAtLSBjaGFuZ2luZyBhbGwgdmFsdWVzIG9mIGEgdmFyaWFibGUgaW4gdGhlIHNhbWUgd2F5LCB0eXBpY2FsbHkgdG8gbWFrZSBpdCBtb3JlIG5vcm1hbCBvciBlYXNpZXIgdG8gaW50ZXJwcmV0CjMuIFsqKkRpc2NyZXRpemF0aW9uKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Rpc2NyZXRpemF0aW9uX29mX2NvbnRpbnVvdXNfZmVhdHVyZXMpe3RhcmdldD0iX2JsYW5rIn0gLS0gY29udmVydGluZyBjb250aW51b3VzIHZhbHVlcyBpbnRvIGRpc2NyZXRlIG9yIG5vbWluYWwgdmFsdWVzIC0gYmlubmluZyBmb3IgZXhhbXBsZSB0byByZWR1Y2UgdGhlIG51bWJlciBvZiBwb3NzaWJsZSBsZXZlbHMgKEhvd2V2ZXIgdGhpcyBpcyBnZW5lcmFsbHkgbm90IGFkdmlzYWJsZSEpCjQuIFsqKkVuY29kaW5nIC8gQ3JlYXRpbmcgRHVtbXkgVmFyaWFibGVzKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0R1bW15X3ZhcmlhYmxlXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAtLSBjcmVhdGluZyBhIG51bWVyaWMgY29kZSBmb3IgY2F0ZWdvcmljYWwgdmFyaWFibGVzCihbKipNb3JlIG9uIER1bW15IFZhcmlhYmxlcyBhbmQgb25lIGhvdCBlbmNvZGluZyoqXShodHRwczovL21lZGl1bS5jb20vcC9iNTg0MGJlM2M0MWEvcmVzcG9uc2VzL3Nob3cpe3RhcmdldD0iX2JsYW5rIn0pCjUuIFsqKkRhdGEgdHlwZSBjb252ZXJzaW9ucyoqXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvaGFibGFyL3ZpZ25ldHRlcy9jb252ZXJ0Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gIC0tIHdoaWNoIG1lYW5zIGNoYW5naW5nIGZyb20gaW50ZWdlciB0byBmYWN0b3Igb3IgbnVtZXJpYyB0byBkYXRlIGV0Yy4KNi4gWyoqSW50ZXJhY3Rpb24qKl0oaHR0cHM6Ly9zdGF0aXN0aWNzYnlqaW0uY29tL3JlZ3Jlc3Npb24vaW50ZXJhY3Rpb24tZWZmZWN0cy8pe3RhcmdldD0iX2JsYW5rIn0gIHRlcm0gYWRkaXRpb24gdG8gdGhlIG1vZGVsIC0tIHdoaWNoIG1lYW5zIHRoYXQgd2Ugd291bGQgYmUgbW9kZWxpbmcgZm9yIHByZWRpY3RvcnMgdGhhdCB3b3VsZCBpbmZsdWVuY2UgdGhlIGNhcGFjaXR5IG9mIGVhY2ggb3RoZXIgdG8gcHJlZGljdCB0aGUgb3V0Y29tZQo3LiBbKipOb3JtYWxpemF0aW9uKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL05vcm1hbGl6YXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IC0tIGNlbnRlcmluZyBhbmQgc2NhbGluZyB0aGUgZGF0YSB0byBhIHNpbWlsYXIgcmFuZ2Ugb2YgdmFsdWVzCjguIFsqKkRpbWVuc2lvbmFsaXR5IFJlZHVjdGlvbi8gU2lnbmFsIEV4dHJhY3Rpb24qKl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRGltZW5zaW9uYWxpdHlfcmVkdWN0aW9uKXt0YXJnZXQ9Il9ibGFuayJ9IC0tIHJlZHVjaW5nIHRoZSBzcGFjZSBvZiBmZWF0dXJlcyBvciBwcmVkaWN0b3JzIHRvIGEgc21hbGxlciBzZXQgb2YgdmFyaWFibGVzIHRoYXQgY2FwdHVyZSB0aGUgdmFyaWF0aW9uIG9yIHNpZ25hbCBpbiB0aGUgb3JpZ2luYWwgdmFyaWFibGVzIChleC4gUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcyBhbmQgSW5kZXBlbmRlbnQgQ29tcG9uZW50IEFuYWx5c2lzKQo5LiAqKkZpbHRlcmluZyoqIC0tIGZpbHRlcmluZyBvcHRpb25zIGZvciByZW1vdmluZyB2YXJpYWJsZXMgKGV4LiByZW1vdmUgdmFyaWFibGVzIHRoYXQgYXJlIGhpZ2hseSBjb3JyZWxhdGVkIHRvIG90aGVycyBvciByZW1vdmUgdmFyaWFibGVzIHdpdGggdmVyeSBsaXR0bGUgdmFyaWFuY2UgYW5kIHRoZXJlZm9yZSBsaWtlbHkgbGl0dGxlIHByZWRpY3RpdmUgY2FwYWNpdHkpCjEwLiBbKipSb3cgb3BlcmF0aW9ucyoqXShodHRwczovL3RhcnRhcnVzLm9yZy9nYXJldGgvbWF0aHMvTGluZWFyX0FsZ2VicmEvcm93X29wZXJhdGlvbnMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IC0tIHBlcmZvcm1pbmcgZnVuY3Rpb25zIG9uIHRoZSB2YWx1ZXMgd2l0aGluIHRoZSByb3dzICAoZXguIHJlYXJyYW5naW5nLCBmaWx0ZXJpbmcsIGltcHV0aW5nKQoxMS4gKipDaGVja2luZyBmdW5jdGlvbnMqKiAtLSBTYW5pdHkgY2hlY2tzIHRvIGxvb2sgZm9yIG1pc3NpbmcgdmFsdWVzLCB0byBsb29rIGF0IHRoZSB2YXJpYWJsZSBjbGFzc2VzIGV0Yy4KCkFsbCBvZiB0aGUgc3RlcCBmdW5jdGlvbnMgbG9vayBsaWtlIGBzdGVwXyooKWAgd2l0aCB0aGUgYCpgIHJlcGxhY2VkIHdpdGggYSBuYW1lLCBleGNlcHQgZm9yIHRoZSBjaGVjayBmdW5jdGlvbnMgd2hpY2ggbG9vayBsaWtlIGBjaGVja18qKClgLgoKVGhlcmUgYXJlIHNldmVyYWwgd2F5cyB0byBzZWxlY3Qgd2hhdCB2YXJpYWJsZXMgdG8gYXBwbHkgc3RlcHMgdG86ICAKCjEuIFVzaW5nIGB0aWR5c2VsZWN0YCBtZXRob2RzOiBgY29udGFpbnMoKWAsIGBtYXRjaGVzKClgLCBgc3RhcnRzX3dpdGgoKWAsIGBlbmRzX3dpdGgoKWAsIGBldmVyeXRoaW5nKClgLCBgbnVtX3JhbmdlKClgICAKMi4gVXNpbmcgdGhlIHR5cGU6IGBhbGxfbm9taW5hbCgpYCwgYGFsbF9udW1lcmljKClgICwgYGhhc190eXBlKClgIAozLiBVc2luZyB0aGUgcm9sZTogYGFsbF9wcmVkaWN0b3JzKClgLCBgYWxsX291dGNvbWVzKClgLCBgaGFzX3JvbGUoKWAKNC4gVXNpbmcgdGhlIG5hbWUgLSB1c2UgdGhlIGFjdHVhbCBuYW1lIG9mIHRoZSB2YXJpYWJsZS92YXJpYWJsZXMgb2YgaW50ZXJlc3QgIAoKTGV0J3MgdHJ5IGFkZGluZyBzb21lIHN0ZXBzIHRvIG91ciByZWNpcGUuCgoKV2UgbWlnaHQgd2FudCB0byBwb3RlbnRpYWxseSBbb25lIGhvdCBlbmNvZGVdKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vd2h5LW9uZS1ob3QtZW5jb2RlLWRhdGEtaW4tbWFjaGluZS1sZWFybmluZy8pe3RhcmdldD0iX2JsYW5rIn0gc29tZSBvZiBvdXIgY2F0ZWdvcmljYWwgdmFyaWFibGVzIHNvIHRoYXQgdGhleSBjYW4gYmUgdXNlZCB3aXRoIGNlcnRhaW4gYWxnb3JpdGhtcy4gCgpXZSBjYW4gZG8gdGhpcyB3aXRoIHRoZSBgc3RlcF9kdW1teSgpYCBmdW5jdGlvbiBhbmQgdGhlIGBvbmVfaG90ID0gVFJVRWAgYXJndW1lbnQuIApPbmUgaG90IGVuY29kaW5nIG1lYW5zIHRoYXQgd2UgZG8gbm90IHNpbXBseSBlbmNvZGUgb3VyIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBudW1lcmljYWxseSwgYXMgb3VyIG51bWVyaWMgYXNzaWdubWVudHMgY2FuIGJlIGludGVycHJldGVkIGJ5IGFsZ29yaXRobXMgYXMgaGF2aW5nIGEgcGFydGljdWxhciByYW5rIG9yIG9yZGVyLiAKSW5zdGVhZCwgYmluYXJ5IHZhcmlhYmxlcyBtYWRlIG9mIDFzIGFuZCAwcyBhcmUgdXNlZCB0byBhcmJpdHJhcmlseSBhc3NpZ24gYSBudW1lcmljIHZhbHVlIHRoYXQgaGFzIG5vIGFwcGFyZW50IG9yZGVyLgoKYGBge3J9CnNpbXBsZV9yZWMgJT4lCiAgc3RlcF9kdW1teShzdGF0ZSwgY291bnR5LCBjaXR5LCB6Y3RhLCBvbmVfaG90ID0gVFJVRSkKYGBgCgpPdXIgYGZpcHNgIHZhcmlhYmxlIGluY2x1ZGVzIGEgbnVtZXJpYyBjb2RlIGZvciBzdGF0ZSBhbmQgY291bnR5IC0gYW5kIHRoZXJlZm9yZSBpcyBlc3NlbnRpYWxseSBhIHByb3h5IGZvciBjb3VudHkuClNpbmNlIHdlIGFscmVhZHkgaGF2ZSBjb3VudHksIHdlIHdpbGwganVzdCB1c2UgaXQgYW5kIGtlZXAgdGhlIGBmaXBzYCBJRCBhcyBhbm90aGVyIElEIHZhcmlhYmxlLgoKV2UgY2FuIHJlbW92ZSB0aGUgYGZpcHNgIHZhcmlhYmxlIGZyb20gdGhlIHByZWRpY3RvcnMgdXNpbmcgYHVwZGF0ZV9yb2xlKClgIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSByb2xlIGlzIG5vIGxvbmdlciBgInByZWRpY3RvciJgLiAKV2UgY2FuIG1ha2UgdGhlIHJvbGUgYW55dGhpbmcgd2Ugd2FudCBhY3R1YWxseSwgc28gd2Ugd2lsbCBrZWVwIGl0IHNvbWV0aGluZyBpZGVudGlmaWFibGUuCgpgYGB7cn0Kc2ltcGxlX3JlYyAlPiUKICB1cGRhdGVfcm9sZSgiZmlwcyIsIG5ld19yb2xlID0gImNvdW50eSBpZCIpCmBgYAoKV2UgbWlnaHQgYWxzbyB3YW50IHRvIHJlbW92ZSB2YXJpYWJsZXMgdGhhdCBhcHBlYXIgdG8gYmUgcmVkdW5kYW50IGFuZCBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQgd2l0aCBvdGhlcnMsIGFzIHdlIGtub3cgZnJvbSBvdXIgZXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcyB0aGF0IG1hbnkgb2Ygb3VyIHZhcmlhYmxlcyBhcmUgY29ycmVsYXRlZCB3aXRoIG9uZSBhbm90aGVyLiAKV2UgY2FuIGRvIHRoaXMgdXNpbmcgdGhlIGBzdGVwX2NvcnIoKWAgZnVuY3Rpb24uCgpXZSBkb24ndCB3YW50IHRvIHJlbW92ZSBzb21lIG9mIG91ciB2YXJpYWJsZXMsIGxpa2UgdGhlIGBDTUFRYCBhbmQgYGFvZGAgdmFyaWFibGVzLCB3ZSBjYW4gc3BlY2lmeSB0aGlzIHVzaW5nIHRoZSBgLWAgc2lnbiBiZWZvcmUgdGhlIG5hbWVzIG9mIHRoZXNlIHZhcmlhYmxlcyBsaWtlIHNvOgoKYGBge3J9CnNpbXBsZV9yZWMgJT4lCiAgc3RlcF9jb3JyKGFsbF9wcmVkaWN0b3JzKCksIC0gQ01BUSwgLSBhb2QpCmBgYAoKCkl0IGlzIGFsc28gYSBnb29kIGlkZWEgdG8gcmVtb3ZlIHZhcmlhYmxlcyB3aXRoIG5lYXItemVybyB2YXJpYW5jZSwgd2hpY2ggY2FuIGJlIGRvbmUgd2l0aCB0aGUgYHN0ZXBfbnp2KClgIGZ1bmN0aW9uLiAKClZhcmlhYmxlcyBoYXZlIGxvdyB2YXJpYW5jZSBpZiBhbGwgdGhlIHZhbHVlcyBhcmUgdmVyeSBzaW1pbGFyLCB0aGUgdmFsdWVzIGFyZSB2ZXJ5IHNwYXJzZSwgb3IgaWYgdGhleSBhcmUgaGlnaGx5IGltYmFsYW5jZWQuIEFnYWluIHdlIGRvbid0IHdhbnQgdG8gcmVtb3ZlIG91ciBgQ01BUWAgYW5kIGBhb2RgIHZhcmlhYmxlcy4KCmBgYHtyfQpzaW1wbGVfcmVjICU+JQogIHN0ZXBfbnp2KGFsbF9wcmVkaWN0b3JzKCksIC0gQ01BUSwgLSBhb2QpCmBgYAoKPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gbGVhcm4gYWJvdXQgZXhhbXBsZXMgd2hlcmUgeW91IG1pZ2h0IGhhdmUgbmVhci16ZXJvIHZhcmlhbmNlIHZhcmlhYmxlczwvc3VtbWFyeT4KCjEpICoqU2ltaWxhciBWYWx1ZXMqKiAtIElmIHRoZSBwb3B1bGF0aW9uIGRlbnNpdHkgd2FzIG5lYXJseSB0aGUgc2FtZSBmb3IgZXZlcnkgemN0YSB0aGF0IGNvbnRhaW5lZCBhIG1vbml0b3IsIHRoZW4ga25vd2luZyB0aGUgcG9wdWxhdGlvbiBkZW5zaXR5IG5lYXIgb3VyIG1vbml0b3Igd291bGQgY29udHJpYnV0ZSBsaXR0bGUgdG8gb3VyIG1vZGVsIGluIGFzc2lzdGluZyB1cyB0byBwcmVkaWN0IG1vbml0b3IgYWlyIHBvbGx1dGlvbiB2YWx1ZXMuIAoyKSAqKlNwYXJzZSBEYXRhKiogLSBJZiBhbGwgb2YgdGhlIG1vbml0b3JzIHdlcmUgaW4gbG9jYXRpb25zIHdoZXJlIHRoZSBwb3B1bGF0aW9ucyBkaWQgbm90IGF0dGVuZCBncmFkdWF0ZSBzY2hvb2wsIHRoZW4gdGhlc2UgdmFsdWVzIHdvdWxkIG1vc3RseSBiZSB6ZXJvLCBhZ2FpbiB0aGlzIHdvdWxkIGRvIHZlcnkgbGl0dGxlIHRvIGhlbHAgdXMgZGlzdGluZ3Vpc2ggb3VyIGFpciBwb2xsdXRpb24gbW9uaXRvcnMuV2hlbiBtYW55IG9mIHRoZSB2YWx1ZXMgYXJlIHplcm8gdGhpcyBpcyBhbHNvIGNhbGxlZCBzcGFyc2UgZGF0YS4gIAozKSAqKkltYmFsYW5jZWQgRGF0YSoqIElmIG5lYXJseSBhbGwgb2YgdGhlIG1vbml0b3JzIHdlcmUgbG9jYXRlZCBpbiBvbmUgcGFydGljdWxhciBzdGF0ZSwgYW5kIGFsbCB0aGUgb3RoZXJzIG9ubHkgaGFkIG9uZSBtb25pdG9yIGVhY2gsIHRoZW4gdGhlIHJlYWwgcHJlZGljdGl2ZSB2YWx1ZSB3b3VsZCBzaW1wbHkgYmUgaW4ga25vd2luZyBpZiBhIG1vbml0b3IgaXMgbG9jYXRlZCBpbiB0aGF0IHBhcnRpY3VsYXIgc3RhdGUgb3Igbm90LiBJbiB0aGlzIGNhc2Ugd2UgZG9uJ3Qgd2FudCB0byByZW1vdmUgb3VyIHZhcmlhYmxlLCB3ZSBqdXN0IHdhbnQgdG8gc2ltcGxpZnkgaXQuCgpTZWUgdGhpcyBbYmxvZyBwb3N0XShodHRwczovL3d3dy5yLWJsb2dnZXJzLmNvbS9uZWFyLXplcm8tdmFyaWFuY2UtcHJlZGljdG9ycy1zaG91bGQtd2UtcmVtb3ZlLXRoZW0vKXt0YXJnZXQ9Il9ibGFuayJ9IGFib3V0IHdoeSByZW1vdmluZyBuZWFyLXplcm8gdmFyaWFuY2UgdmFyaWFibGVzIGlzbid0IGFsd2F5cyBhIGdvb2QgaWRlYSBpZiB3ZSB0aGluayB0aGF0IGEgdmFyaWFibGUgbWlnaHQgYmUgZXNwZWNpYWxseSBpbmZvcm1hdGl2ZS4KCjwvZGV0YWlscz4KCkxldCdzIHB1dCBhbGwgdGhpcyB0b2dldGhlciBub3cuIAoKKipSZW1lbWJlcjogaXQgaXMgaW1wb3J0YW50IHRvIGFkZCB0aGUgc3RlcHMgdG8gdGhlIHJlY2lwZSBpbiBhbiBvcmRlciB0aGF0IG1ha2VzIHNlbnNlIGp1c3QgbGlrZSB3aXRoIGEgY29va2luZyByZWNpcGUuKioKCkZpcnN0LCB3ZSBhcmUgZ29pbmcgdG8gY3JlYXRlIG51bWVyaWMgdmFsdWVzIGZvciBvdXIgY2F0ZWdvcmljYWwgdmFyaWFibGVzLCB0aGVuIHdlIHdpbGwgbG9vayBhdCBjb3JyZWxhdGlvbiBhbmQgbmVhci16ZXJvIHZhcmlhbmNlLiAKQWdhaW4sIHdlIGRvIG5vdCB3YW50IHRvIHJlbW92ZSB0aGUgYENNQVFgIGFuZCBgYW9kYCB2YXJpYWJsZXMsIHNvIHdlIGNhbiBtYWtlIHN1cmUgdGhleSBhcmUga2VwdCBpbiB0aGUgbW9kZWwgYnkgZXhjbHVkaW5nIHRoZW0gZnJvbSB0aG9zZSBzdGVwcy4gCklmIHdlIHNwZWNpZmljYWxseSB3YW50ZWQgdG8gcmVtb3ZlIGEgcHJlZGljdG9yIHdlIGNvdWxkIHVzZSBgc3RlcF9ybSgpYC4KCmBgYHtyfQpzaW1wbGVfcmVjICU8PiUKICB1cGRhdGVfcm9sZSgiZmlwcyIsIG5ld19yb2xlID0gImNvdW50eSBpZCIpICU+JQogIHN0ZXBfZHVtbXkoc3RhdGUsIGNvdW50eSwgY2l0eSwgemN0YSwgb25lX2hvdCA9IFRSVUUpICU+JQogIHN0ZXBfY29ycihhbGxfcHJlZGljdG9ycygpLCAtIENNQVEsIC0gYW9kKSU+JQogIHN0ZXBfbnp2KGFsbF9wcmVkaWN0b3JzKCksIC0gQ01BUSwgLSBhb2QpCiAgCnNpbXBsZV9yZWMKYGBgCgoKCiMjIFJ1bm5pbmcgdGhlIHByZS1wcm9jZXNzaW5nCgojIyMgU3RlcCAxOiBVcGRhdGUgdGhlIHJlY2lwZSB3aXRoIHRyYWluaW5nIGRhdGEgdXNpbmcgYHByZXAoKWAKClRoZSBuZXh0IG1ham9yIGZ1bmN0aW9uIG9mIHRoZSBgcmVjaXBlc2AgcGFja2FnZSBpcyBgcHJlcCgpYC4KVGhpcyBmdW5jdGlvbiB1cGRhdGVzIHRoZSByZWNpcGUgb2JqZWN0IGJhc2VkIG9uIHRoZSB0cmFpbmluZyBkYXRhLiAKSXQgZXN0aW1hdGVzIHBhcmFtZXRlcnMgKGVzdGltYXRpbmcgdGhlIHJlcXVpcmVkIHF1YW50aXRpZXMgYW5kIHN0YXRpc3RpY3MgcmVxdWlyZWQgYnkgdGhlIHN0ZXBzIGZvciB0aGUgdmFyaWFibGVzKSBmb3IgcHJlLXByb2Nlc3NpbmcgYW5kIHVwZGF0ZXMgdGhlIHZhcmlhYmxlcyByb2xlcywgYXMgc29tZSBvZiB0aGUgcHJlZGljdG9ycyBtYXkgYmUgcmVtb3ZlZCwgdGhpcyBhbGxvd3MgdGhlIHJlY2lwZSB0byBiZSByZWFkeSB0byB1c2Ugb24gb3RoZXIgZGF0YSBzZXRzLiAKSXQgKipkb2VzIG5vdCBuZWNlc3NhcmlseSBhY3R1YWxseSBleGVjdXRlIHRoZSBwcmUtcHJvY2Vzc2luZyBpdHNlbGYqKiwgaG93ZXZlciB3ZSB3aWxsIHNwZWNpZnkgaW4gYXJndW1lbnQgZm9yIGl0IHRvIGRvIHRoaXMgc28gdGhhdCB3ZSBjYW4gdGFrZSBhIGxvb2sgYXQgdGhlIHByZS1wcm9jZXNzZWQgZGF0YS4KCgpUaGVyZSBhcmUgc29tZSBpbXBvcnRhbnQgYXJndW1lbnRzIHRvIGtub3cgYWJvdXQ6CgoxLiBgdHJhaW5pbmdgIC0geW91IG11c3Qgc3VwcGx5IGEgdHJhaW5pbmcgZGF0YSBzZXQgdG8gZXN0aW1hdGUgcGFyYW1ldGVycyBmb3IgcHJlLXByb2Nlc3Npbmcgb3BlcmF0aW9ucyAocmVjaXBlIHN0ZXBzKSAtIHRoaXMgbWF5IGFscmVhZHkgYmUgaW5jbHVkZWQgaW4geW91ciByZWNpcGUgLSBhcyBpcyB0aGUgY2FzZSBmb3IgdXMKMi4gYGZyZXNoYCAtIGlmIGBmcmVzaD1UUlVFYCwgLSB3aWxsIHJldHJhaW4gYW5kIGVzdGltYXRlIHBhcmFtZXRlcnMgZm9yIGFueSBwcmV2aW91cyBzdGVwcyB0aGF0IHdlcmUgYWxyZWFkeSBwcmVwcGVkIGlmIHlvdSBhZGQgbW9yZSBzdGVwcyB0byB0aGUgcmVjaXBlCjMuIGB2ZXJib3NlYCAtIGlmIGB2ZXJib3NlPVRSVUVgLCBzaG93cyB0aGUgcHJvZ3Jlc3MgYXMgdGhlIHN0ZXBzIGFyZSBldmFsdWF0ZWQgYW5kIHRoZSBzaXplIG9mIHRoZSBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIHNldAo0LiBgcmV0YWluYCAtIGlmIGByZXRhaW49VFJVRWAsIHRoZW4gdGhlIHByZS1wcm9jZXNzZWQgdHJhaW5pbmcgc2V0IHdpbGwgYmUgc2F2ZWQgd2l0aGluIHRoZSByZWNpcGUgKGFzIHRlbXBsYXRlKS4gVGhpcyBpcyBnb29kIGlmIHlvdSBhcmUgbGlrZWx5IHRvIGFkZCBtb3JlIHN0ZXBzIGFuZCBkbyBub3Qgd2FudCB0byByZXJ1biB0aGUgYHByZXAoKWAgb24gdGhlIHByZXZpb3VzIHN0ZXBzLiBIb3dldmVyIHRoaXMgY2FuIG1ha2UgdGhlIHJlY2lwZSBzaXplIGxhcmdlLiBUaGlzIGlzIG5lY2Vzc2FyeSBpZiB5b3Ugd2FudCB0byBhY3R1YWxseSBsb29rIGF0IHRoZSBwcmUtcHJvY2Vzc2VkIGRhdGEuCgpMZXQncyB0cnkgb3V0IHRoZSBgcHJlcCgpYCBmdW5jdGlvbjogCgpgYGB7cn0KcHJlcHBlZF9yZWMgPC0gcHJlcChzaW1wbGVfcmVjLCB2ZXJib3NlID0gVFJVRSwgcmV0YWluID0gVFJVRSApCm5hbWVzKHByZXBwZWRfcmVjKQpgYGAKClRoZXJlIGFyZSBhbHNvIGxvdHMgb2YgdXNlZnVsIHRoaW5ncyB0byBjaGVja291dCBpbiB0aGUgb3V0cHV0IG9mIGBwcmVwKClgLgpZb3UgY2FuIHNlZToKCjEuIHRoZSBgc3RlcHNgIHRoYXQgd2VyZSBydW4gIAoyLiB0aGUgb3JpZ2luYWwgdmFyaWFibGUgaW5mbyAoYHZhcl9pbmZvYCkgIAozLiB0aGUgdXBkYXRlZCB2YXJpYWJsZSBpbmZvIGFmdGVyIHByZS1wcm9jZXNzaW5nIChgdGVybV9pbmZvYCkKNC4gdGhlIG5ldyBgbGV2ZWxzYCBvZiB0aGUgdmFyaWFibGVzIAo1LiB0aGUgb3JpZ2luYWwgbGV2ZWxzIG9mIHRoZSB2YXJpYWJsZXMgKGBvcmlnX2x2bHNgKQo2LiBpbmZvIGFib3V0IHRoZSB0cmFpbmluZyBkYXRhIHNldCBzaXplIGFuZCBjb21wbGV0ZW5lc3MgKGB0cl9pbmZvYCkKCioqTm90ZSoqOiBZb3UgbWF5IHNlZSB0aGUgYHByZXAucmVjaXBlKClgIGZ1bmN0aW9uIGluIG1hdGVyaWFsIHRoYXQgeW91IHJlYWQgYWJvdXQgdGhlIGByZWNpcGVzYCBwYWNrYWdlLiBUaGlzIGlzIHJlZmVycmluZyB0byB0aGUgYHByZXAoKWAgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlLgoKCiMjIyBTdGVwIDI6IEV4dHJhY3QgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhIHVzaW5nIGBiYWtlKClgCgpTaW5jZSB3ZSByZXRhaW5lZCBvdXIgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhIChpLmUuIGBwcmVwKHJldGFpbj1UUlVFKWApLCB3ZSBjYW4gdGFrZSBhIGxvb2sgYXQgaXQgbGlrZSBieSB1c2luZyB0aGUgYGJha2UoKWAgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlIGxpa2UgdGhpczoKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjQwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwidHJhaW5pbmdfcHJlcHJvY2Vzc2luZ19yZWNpcGVzMy5wbmciKSkKYGBgCgpMZXQncyBiYWtlISAKClNpbmNlIHdlIGRvbid0IGhhdmUgbmV3IGRhdGEgKHdlIGFyZW4ndCBsb29raW5nIGF0IHRoZSB0ZXN0aW5nIGRhdGEpLCB3ZSBuZWVkIHRvIHNwZWNpZnkgdGhpcyB3aXRoIGBuZXdfZGF0YSA9IE5VTExgLgoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cn0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQpiYWtlZF90cmFpbiA8LSBiYWtlKHByZXBwZWRfcmVjLCBuZXdfZGF0YSA9IE5VTEwpCmdsaW1wc2UoYmFrZWRfdHJhaW4pCmBgYAojIyMjCgoqKk5vdGUqKi0gdGhpcyBwcm9jZXNzIHVzZWQgdG8gcmVxdWlyZSB0aGUgYGp1aWNlKClgIGZ1bmN0aW9uLgoKRm9yIGVhc3kgY29tcGFyaXNvbiBzYWtlIC0gaGVyZSBpcyBvdXIgb3JpZ2luYWwgZGF0YToKCiMjIyMgey5zY3JvbGxhYmxlIH0KCmBgYHtyfQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhCmdsaW1wc2UocG0pCmBgYAojIyMjCgpOb3RpY2UgaG93IHdlIG9ubHkgaGF2ZSAzNiB2YXJpYWJsZXMgbm93IGluc3RlYWQgb2YgNTAhIApUd28gb2YgdGhlc2UgYXJlIG91ciBJRCB2YXJpYWJsZXMgKGBmaXBzYCBhbmQgdGhlIGFjdHVhbCBtb25pdG9yIElEIChgaWRgKSkgYW5kIG9uZSBpcyBvdXIgb3V0Y29tZSAoYHZhbHVlYCkuIApUaHVzIHdlIG9ubHkgaGF2ZSAzMyBwcmVkaWN0b3JzIG5vdy4gCldlIGNhbiBhbHNvIHNlZSB0aGF0IHdlIG5vIGxvbmdlciBoYXZlIGFueSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMuIApWYXJpYWJsZXMgbGlrZSBgc3RhdGVgIGFyZSBnb25lIGFuZCBvbmx5IGBzdGF0ZV9DYWxpZm9ybmlhYCByZW1haW5zIGFzIGl0IHdhcyB0aGUgb25seSBzdGF0ZSBpZGVudGl0eSB0byBoYXZlIG5vbnplcm8gdmFyaWFuY2UuCldlIGNhbiBhbHNvIHNlZSB0aGF0IHRoZXJlIHdlcmUgbW9yZSBtb25pdG9ycyBsaXN0ZWQgYXMgYCJOb3QgaW4gYSBjaXR5ImAgdGhhbiBhbnkgY2l0eS4gCgpXZSBjYW4gc2VlIHRoYXQgQ2FsaWZvcm5pYSBoYWQgdGhlIGxhcmdlc3QgbnVtYmVyIG9mIG1vbml0b3JzIGNvbXBhcmVkIHRvIHRoZSBvdGhlciBzdGF0ZXMuCgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpwbSAlPiUgY291bnQoc3RhdGUpIApgYGAKCgpTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0OgoKIyMjIyB7LnNjcm9sbGFibGUgfQoKYGBge3IsIGVjaG8gPSBGQUxTRX0KcG0gJT4lIGNvdW50KHN0YXRlKSAgJT4lCiAgcHJpbnQobiA9IDFlMykKYGBgCgojIyMjCgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpwbSAlPiUgY291bnQoY2l0eSkKYGBgCgpTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0OgoKIyMjIyB7LnNjcm9sbGFibGUgfQoKYGBge3IsIGVjaG89RkFMU0V9CnBtICU+JSBjb3VudChjaXR5KSAlPiUKICBwcmludChuID0gMWUzKQpgYGAKCiMjIyMKCioqTm90ZSoqOiBSZWNhbGwgdGhhdCB5b3UgbXVzdCBzcGVjaWZ5IGByZXRhaW4gPSBUUlVFYCBhcmd1bWVudCBvZiB0aGUgYHByZXAoKWAgZnVuY3Rpb24gdG8gdXNlIGBiYWtlKClgLgoKIyMjIFN0ZXAgMzogRXh0cmFjdCBwcmUtcHJvY2Vzc2VkIHRlc3RpbmcgZGF0YSB1c2luZyBgYmFrZSgpYAoKQWNjb3JkaW5nIHRvIHRoZSBgdGlkeW1vZGVsc2AgZG9jdW1lbnRhdGlvbjoKCj4gYGJha2UoKWAgdGFrZXMgYSB0cmFpbmVkIHJlY2lwZSBhbmQgYXBwbGllcyB0aGUgb3BlcmF0aW9ucyB0byBhIGRhdGEgc2V0IHRvIGNyZWF0ZSBhIGRlc2lnbiBtYXRyaXguCiBGb3IgZXhhbXBsZTogaXQgYXBwbGllcyB0aGUgY2VudGVyaW5nIHRvIG5ldyBkYXRhIHNldHMgdXNpbmcgdGhlc2UgbWVhbnMgdXNlZCB0byBjcmVhdGUgdGhlIHJlY2lwZS4KClRoZXJlZm9yZSwgaWYgeW91IHdhbnRlZCB0byBsb29rIGF0IHRoZSBwcmUtcHJvY2Vzc2VkIHRlc3RpbmcgZGF0YSB5b3Ugd291bGQgdXNlIHRoZSBgYmFrZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UuCihZb3UgZ2VuZXJhbGx5IHdhbnQgdG8gbGVhdmUgeW91ciB0ZXN0aW5nIGRhdGEgYWxvbmUsIGJ1dCBpdCBpcyBnb29kIHRvIGxvb2sgZm9yIGlzc3VlcyBsaWtlIHRoZSBpbnRyb2R1Y3Rpb24gb2YgTkEgdmFsdWVzKS4KCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjQwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwidGVzdGluZ19wcmVwcm9jZXNzaW5nX3JlY2lwZXM0LnBuZyIpKQpgYGAKCkxldCdzIGJha2UhIAoKIyMjIyB7LnNjcm9sbGFibGUgfQpgYGB7cix9CiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKYmFrZWRfdGVzdF9wbSA8LSByZWNpcGVzOjpiYWtlKHByZXBwZWRfcmVjLCBuZXdfZGF0YSA9IHRlc3RfcG0pCmdsaW1wc2UoYmFrZWRfdGVzdF9wbSkKYGBgCiMjIyMKCgpOb3RpY2UgdGhhdCBvdXIgYGNpdHlfTm90LmluLmEuY2l0eWAgdmFyaWFibGUgc2VlbXMgdG8gYmUgTkEgdmFsdWVzLiAKV2h5IG1pZ2h0IHRoYXQgYmU/CgpBaCEgUGVyaGFwcyBpdCBpcyBiZWNhdXNlIHNvbWUgb2Ygb3VyIGxldmVscyB3ZXJlIG5vdCBwcmV2aW91c2x5IHNlZW4gaW4gdGhlIHRyYWluaW5nIHNldCEKCkxldCdzIHRha2UgYSBsb29rIHVzaW5nIHRoZSBbc2V0IG9wZXJhdGlvbnNdKGh0dHBzOi8vd3d3LnByb2JhYmlsaXR5Y291cnNlLmNvbS9jaGFwdGVyMS8xXzJfMl9zZXRfb3BlcmF0aW9ucy5waHApe3RhcmdldD0iX2JsYW5rIn0gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4gCldlIGNhbiB0YWtlIGEgbG9vayBhdCBjaXRpZXMgdGhhdCB3ZXJlIGRpZmZlcmVudCBiZXR3ZWVuIHRoZSB0ZXN0IGFuZCB0cmFpbmluZyBzZXQuCgpgYGB7cn0KdHJhaW5jaXRpZXMgPC0gdHJhaW5fcG0gJT4lIGRpc3RpbmN0KGNpdHkpCnRlc3RjaXRpZXMgPC0gdGVzdF9wbSAlPiUgZGlzdGluY3QoY2l0eSkKCiNnZXQgdGhlIG51bWJlciBvZiBjaXRpZXMgdGhhdCB3ZXJlIGRpZmZlcmVudApkaW0oZHBseXI6OnNldGRpZmYodHJhaW5jaXRpZXMsIHRlc3RjaXRpZXMpKQoKI2dldCB0aGUgbnVtYmVyIG9mIGNpdGllcyB0aGF0IG92ZXJsYXBwZWQKZGltKGRwbHlyOjppbnRlcnNlY3QodHJhaW5jaXRpZXMsIHRlc3RjaXRpZXMpKQpgYGAKCkluZGVlZCwgdGhlcmUgYXJlIGxvdHMgb2YgZGlmZmVyZW50IGNpdGllcyBpbiBvdXIgdGVzdCBkYXRhIHRoYXQgYXJlIG5vdCBpbiBvdXIgdHJhaW5pbmcgZGF0YSEKCgpTbywgbGV0IGdvIGJhY2sgdG8gb3VyIGBwbWAgZGF0YSBzZXQgYW5kIG1vZGlmeSB0aGUgYGNpdHlgIHZhcmlhYmxlIHRvIGp1c3QgYmUgdmFsdWVzIG9mIGBpbiBhIGNpdHlgIG9yIGBub3QgaW4gYSBjaXR5YCB1c2luZyB0aGUgYGNhc2Vfd2hlbigpYCBmdW5jdGlvbiBvZiBgZHBseXJgLgpUaGlzIGZ1bmN0aW9uIGFsbG93cyB5b3UgdG8gdmVjdG9yaXplIG11bHRpcGxlIGBpZl9lbHNlKClgIHN0YXRlbWVudHMuCgpgYGB7cn0KcG0gJT4lCiAgbXV0YXRlKGNpdHkgPSBjYXNlX3doZW4oY2l0eSA9PSAiTm90IGluIGEgY2l0eSIgfiAiTm90IGluIGEgY2l0eSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2l0eSAhPSAiTm90IGluIGEgY2l0eSIgfiAiSW4gYSBjaXR5IikpCmBgYAoKQWx0ZXJuYXRpdmVseSB5b3UgY291bGQgY3JlYXRlIGEgW2N1c3RvbSBzdGVwIGZ1bmN0aW9uXShodHRwczovL3JlY2lwZXMudGlkeW1vZGVscy5vcmcvYXJ0aWNsZXMvQ3VzdG9tX1N0ZXBzLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gdG8gZG8gdGhpcyBhbmQgYWRkIHRoaXMgdG8geW91ciByZWNpcGUsIGJ1dCB0aGF0IGlzIGJleW9uZCB0aGUgc2NvcGUgb2YgdGhpcyBjYXNlIHN0dWR5LiAKCldlIHdpbGwgbmVlZCB0byByZXBlYXQgYWxsIHRoZSBzdGVwcyAoc3BsaXR0aW5nIHRoZSBkYXRhLCBwcmUtcHJvY2Vzc2luZywgZXRjKSBhcyB0aGUgbGV2ZWxzIG9mIG91ciB2YXJpYWJsZXMgaGF2ZSBub3cgY2hhbmdlZC4gCgpXaGlsZSB3ZSBhcmUgZG9pbmcgdGhpcywgd2UgbWlnaHQgYWxzbyBoYXZlIHRoaXMgaXNzdWUgZm9yIGBjb3VudHlgLiAKClRoZSBgY291bnR5YCB2YXJpYWJsZXMgYXBwZWFycyB0byBnZXQgZHJvcHBlZCBkdWUgdG8gZWl0aGVyIGNvcnJlbGF0aW9uIG9yIG5lYXIgemVybyB2YXJpYW5jZS4gCgpJdCBpcyBsaWtlbHkgZHVlIHRvIG5lYXIgemVybyB2YXJpYW5jZSBiZWNhdXNlIHRoaXMgaXMgdGhlIG1vcmUgZ3JhbnVsYXIgb2YgdGhlc2UgZ2VvZ3JhcGhpYyBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYW5kIGxpa2VseSBzcGFyc2UuCgpgYGB7cn0KcG0gJTw+JQogIG11dGF0ZShjaXR5ID0gY2FzZV93aGVuKGNpdHkgPT0gIk5vdCBpbiBhIGNpdHkiIH4gIk5vdCBpbiBhIGNpdHkiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNpdHkgIT0gIk5vdCBpbiBhIGNpdHkiIH4gIkluIGEgY2l0eSIpKQoKc2V0LnNlZWQoMTIzNCkgIyBzYW1lIHNlZWQgYXMgYmVmb3JlCnBtX3NwbGl0IDwtcnNhbXBsZTo6aW5pdGlhbF9zcGxpdChkYXRhID0gcG0sIHByb3AgPSAyLzMpCnBtX3NwbGl0CiB0cmFpbl9wbSA8LXJzYW1wbGU6OnRyYWluaW5nKHBtX3NwbGl0KQogdGVzdF9wbSA8LXJzYW1wbGU6OnRlc3RpbmcocG1fc3BsaXQpCmBgYAoKCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpTZWUgaWYgeW91IGNhbiBjb21lIHVwIHdpdGggdGhlIGNvZGUgZm9yIHRoZSBuZXcgcmVjaXBlLgoKIyMjIwoKKioqCgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBjb2RlIGZvciB0aGUgbmV3IHJlY2lwZS4gPC9zdW1tYXJ5PgoKCmBgYHtyfQpub3ZlbF9yZWMgPC1yZWNpcGUodHJhaW5fcG0pICU+JQogICAgdXBkYXRlX3JvbGUoZXZlcnl0aGluZygpLCBuZXdfcm9sZSA9ICJwcmVkaWN0b3IiKSAlPiUKICAgIHVwZGF0ZV9yb2xlKHZhbHVlLCBuZXdfcm9sZSA9ICJvdXRjb21lIikgJT4lCiAgICB1cGRhdGVfcm9sZShpZCwgbmV3X3JvbGUgPSAiaWQgdmFyaWFibGUiKSAlPiUKICAgIHVwZGF0ZV9yb2xlKCJmaXBzIiwgbmV3X3JvbGUgPSAiY291bnR5IGlkIikgJT4lCiAgICBzdGVwX2R1bW15KHN0YXRlLCBjb3VudHksIGNpdHksIHpjdGEsIG9uZV9ob3QgPSBUUlVFKSAlPiUKICAgIHN0ZXBfY29ycihhbGxfbnVtZXJpYygpKSAlPiUKICAgIHN0ZXBfbnp2KGFsbF9udW1lcmljKCkpIApgYGAKPC9kZXRhaWxzPgoqKioKCmBgYHtyfQpub3ZlbF9yZWMKYGBgCgoKCk5vdyBsZXQncyByZXRyYWluIG91ciB0cmFpbmluZyBkYXRhIGFuZCB0cnkgYmFraW5nIG91ciB0ZXN0IGRhdGEuCgoKCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpEbyB5b3UgcmVjYWxsIGhvdyB0byBwcmUtcHJvY2VzcyBhbmQgZXh0cmFjdCB0aGUgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhPwoKIyMjIwoKKioqCgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBhbnN3ZXIuIDwvc3VtbWFyeT4KCmBgYHtyfQpwcmVwcGVkX3JlYyA8LSBwcmVwKG5vdmVsX3JlYywgdmVyYm9zZSA9IFRSVUUsIHJldGFpbiA9IFRSVUUpCmJha2VkX3RyYWluIDwtIGJha2UocHJlcHBlZF9yZWMsIG5ld19kYXRhID0gTlVMTCkKYGBgCjwvZGV0YWlscz4gCioqKgoKCiMjIyMgey5zY3JvbGxhYmxlIH0KYGBge3J9CiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCEKZ2xpbXBzZShiYWtlZF90cmFpbikKYGBgCgojIyMjCgpBbmQgbm93LCBsZXQncyB0cnkgYmFraW5nIG91ciB0ZXN0IHNldCB0byBzZWUgaWYgd2Ugc3RpbGwgaGF2ZSBgTkFgIHZhbHVlcy4KCiMjIyMgey5zY3JvbGxhYmxlIH0KCmBgYHtyfQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhCmJha2VkX3Rlc3RfcG0gPC0gcmVjaXBlczo6YmFrZShwcmVwcGVkX3JlYywgbmV3X2RhdGEgPSB0ZXN0X3BtKQoKZ2xpbXBzZShiYWtlZF90ZXN0X3BtKQpgYGAKCiMjIyMKCkdyZWF0LCBub3cgd2Ugbm8gbG9uZ2VyIGhhdmUgYE5BYCB2YWx1ZXMhIDopCgoqKk5vdGUqKjogaWYgeW91IHVzZSB0aGUgc2tpcCBvcHRpb24gZm9yIHNvbWUgb2YgdGhlIHByZS1wcm9jZXNzaW5nIHN0ZXBzLCBiZSBjYXJlZnVsLiAKYGp1aWNlKClgIHdpbGwgc2hvdyBhbGwgb2YgdGhlIHJlc3VsdHMgaWdub3JpbmcgYHNraXAgPSBUUlVFYCAoYXMgeW91IGNhbiBzdGlsbCB1c2UgdGhpcyBmdW5jdGlvbiBpZiB5b3UgcGVyZmVyIGl0IHRvIGBiYWtlKClgKS4KYGJha2UoKWAgd2lsbCBub3QgbmVjZXNzYXJpbHkgY29uZHVjdCB0aGVzZSBzdGVwcyBvbiB0aGUgbmV3IGRhdGEuCgoKIyMgU3BlY2lmeWluZyB0aGUgbW9kZWwKClNvIGZhciB3ZSBoYXZlIHVzZWQgdGhlIHBhY2thZ2VzIGByc2FtcGxlYCB0byBzcGxpdCB0aGUgZGF0YSBhbmQgYHJlY2lwZXNgIHRvIGFzc2lnbiB2YXJpYWJsZSB0eXBlcywgYW5kIHRvIHNwZWNpZnkgYW5kIHByZXAgb3VyIHByZS1wcm9jZXNzaW5nIChhcyB3ZWxsIGFzIHRvIG9wdGlvbmFsbHkgZXh0cmFjdCB0aGUgcHJlLXByb2Nlc3NlZCBkYXRhKS4KCldlIHdpbGwgbm93IHVzZSB0aGUgYHBhcnNuaXBgIHBhY2thZ2UgKHdoaWNoIGlzIHNpbWlsYXIgdG8gdGhlIHByZXZpb3VzIGBjYXJldGAgcGFja2FnZSAtIGFuZCBoZW5jZSB3aHkgaXQgaXMgbmFtZWQgYWZ0ZXIgdGhlIHZlZ2V0YWJsZSkgdG8gc3BlY2lmeSBvdXIgbW9kZWwuCgpUaGVyZSBhcmUgZm91ciB0aGluZ3Mgd2UgbmVlZCB0byBkZWZpbmUgYWJvdXQgb3VyIG1vZGVsOiAgCgoxLiBUaGUgKip0eXBlKiogb2YgbW9kZWwgKHVzaW5nIHNwZWNpZmljIGZ1bmN0aW9ucyBpbiBwYXJzbmlwIGxpa2UgYHJhbmRfZm9yZXN0KClgLCBgbG9naXN0aWNfcmVnKClgIGV0Yy4pICAKMi4gVGhlIHBhY2thZ2Ugb3IgKiplbmdpbmUqKiB0aGF0IHdlIHdpbGwgdXNlIHRvIGltcGxlbWVudCB0aGUgdHlwZSBvZiBtb2RlbCBzZWxlY3RlZCAodXNpbmcgdGhlIGBzZXRfZW5naW5lKClgIGZ1bmN0aW9uKSAKMy4gVGhlICoqbW9kZSoqIG9mIGxlYXJuaW5nIC0gY2xhc3NpZmljYXRpb24gb3IgcmVncmVzc2lvbiAodXNpbmcgdGhlIGBzZXRfbW9kZSgpYCBmdW5jdGlvbikgCjQuIEFueSAqKmFyZ3VtZW50cyoqIG5lY2Vzc2FyeSBmb3IgdGhlIG1vZGVsL3BhY2thZ2Ugc2VsZWN0ZWQgKHVzaW5nIHRoZSBgc2V0X2FyZ3MoKWBmdW5jdGlvbiAtICBmb3IgZXhhbXBsZSB0aGUgYG10cnkgPWAgYXJndW1lbnQgZm9yIHJhbmRvbSBmb3Jlc3Qgd2hpY2ggaXMgdGhlIG51bWJlciBvZiB2YXJpYWJsZXMgdG8gYmUgdXNlZCBhcyBvcHRpb25zIGZvciBzcGxpdHRpbmcgYXQgZWFjaCB0cmVlIG5vZGUpCgpMZXQncyB3YWxrIHRocm91Z2ggdGhlc2Ugc3RlcHMgb25lIGJ5IG9uZS4gCkZvciBvdXIgY2FzZSwgd2UgYXJlIGdvaW5nIHRvIHN0YXJ0IG91ciBhbmFseXNpcyB3aXRoIGEgbGluZWFyIHJlZ3Jlc3Npb24gYnV0IHdlIHdpbGwgZGVtb25zdHJhdGUgaG93IHdlIGNhbiB0cnkgZGlmZmVyZW50IG1vZGVscy4KClRoZSBmaXJzdCBzdGVwIGlzIHRvIGRlZmluZSB3aGF0IHR5cGUgb2YgbW9kZWwgd2Ugd291bGQgbGlrZSB0byB1c2UuIApTZWUgW2hlcmVdKGh0dHBzOi8vd3d3LnRpZHltb2RlbHMub3JnL2ZpbmQvcGFyc25pcC8pe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vZGVsaW5nIG9wdGlvbnMgaW4gYHBhcnNuaXBgLgoKCmBgYHtyfQpQTV9tb2RlbCA8LSBwYXJzbmlwOjpsaW5lYXJfcmVnKCkgIyBQTSB3YXMgdXNlZCBpbiB0aGUgbmFtZSBmb3IgcGFydGljdWxhdGUgbWF0dGVyClBNX21vZGVsCmBgYAoKT0suIFNvIGZhciwgYWxsIHdlIGhhdmUgZGVmaW5lZCBpcyB0aGF0IHdlIHdhbnQgdG8gdXNlIGEgbGluZWFyIHJlZ3Jlc3Npb24uLi4gIApMZXQncyB0ZWxsIGBwYXJzbmlwYCBtb3JlIGFib3V0IHdoYXQgd2Ugd2FudC4KCldlIHdvdWxkIGxpa2UgdG8gdXNlIHRoZSBbb3JkaW5hcnkgbGVhc3Qgc3F1YXJlc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvT3JkaW5hcnlfbGVhc3Rfc3F1YXJlcykgbWV0aG9kIHRvIGZpdCBvdXIgbGluZWFyIHJlZ3Jlc3Npb24uIApTbyB3ZSB3aWxsIHRlbGwgYHBhcnNuaXBgIHRoYXQgd2Ugd2FudCB0byB1c2UgdGhlIGBsbWAgcGFja2FnZSB0byBpbXBsZW1lbnQgb3VyIGxpbmVhciByZWdyZXNzaW9uICh0aGVyZSBhcmUgbWFueSBvcHRpb25zIGFjdHVhbGx5IHN1Y2ggYXMgW2Byc3RhbmBdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yc3Rhbi92aWduZXR0ZXMvcnN0YW4uaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgW2BnbG1uZXRgXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZ2xtbmV0L2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0sIFtga2VyYXNgXShodHRwczovL2tlcmFzLnJzdHVkaW8uY29tLyl7dGFyZ2V0PSJfYmxhbmsifSwgYW5kIFtgc3BhcmtseXJgXShodHRwczovL3RoZXJpbnNwYXJrLmNvbS9zdGFydGluZy5odG1sI3N0YXJ0aW5nLXNwYXJrbHlyLWhlbGxvLXdvcmxkKXt0YXJnZXQ9Il9ibGFuayJ9KS4gU2VlIFtoZXJlXShodHRwczovL3BhcnNuaXAudGlkeW1vZGVscy5vcmcvcmVmZXJlbmNlL2xpbmVhcl9yZWcuaHRtbCkgZm9yIGEgZGVzY3JpcHRpb24gb2YgdGhlIGRpZmZlcmVuY2VzIGFuZCB1c2luZyB0aGVzZSBkaWZmZXJlbnQgZW5naW5lcyB3aXRoIGBwYXJzbmlwYC4KCldlIHdpbGwgZG8gc28gYnkgdXNpbmcgdGhlIGBzZXRfZW5naW5lKClgIGZ1bmN0aW9uIG9mIHRoZSBgcGFyc25pcGAgcGFja2FnZS4KCmBgYHtyfQpsbV9QTV9tb2RlbCA8LSAKICBQTV9tb2RlbCAgJT4lCiAgcGFyc25pcDo6c2V0X2VuZ2luZSgibG0iKQoKbG1fUE1fbW9kZWwKYGBgCgpJbiBzb21lIGNhc2VzIHNvbWUgcGFja2FnZXMgY2FuIGRvIGVpdGhlciBjbGFzc2lmaWNhdGlvbiBvciBwcmVkaWN0aW9uLCBzbyBpdCBpcyBhIGdvb2QgaWRlYSB0byBzcGVjaWZ5IHdoaWNoIG1vZGUgeW91IGludGVuZCB0byBwZXJmb3JtLiAKSGVyZSwgd2UgYWltIHRvIHByZWRpY3QgdGhlIGFpciBwb2xsdXRpb24uIApZb3UgY2FuIGRvIHRoaXMgd2l0aCB0aGUgYHNldF9tb2RlKClgIGZ1bmN0aW9uIG9mIHRoZSBgcGFyc25pcGAgcGFja2FnZSwgYnkgdXNpbmcgZWl0aGVyIGBzZXRfbW9kZSgiY2xhc3NpZmljYXRpb24iKWAgb3IgYHNldF9tb2RlKCJyZWdyZXNzaW9uIilgLgoKYGBge3J9CmxtX1BNX21vZGVsIDwtIAogIFBNX21vZGVsICAlPiUKICBwYXJzbmlwOjpzZXRfZW5naW5lKCJsbSIpICU+JQogIHNldF9tb2RlKCJyZWdyZXNzaW9uIikKCmxtX1BNX21vZGVsCmBgYAoKIyMgRml0dGluZyB0aGUgbW9kZWwKCldlIGNhbiAgdXNlIHRoZSBgcGFyc25pcGAgcGFja2FnZSB3aXRoIGEgbmV3ZXIgcGFja2FnZSBjYWxsZWQgYHdvcmtmbG93c2AgdG8gZml0IG91ciBtb2RlbC4gCgpUaGUgYHdvcmtmbG93c2AgcGFja2FnZSBhbGxvd3MgdXMgdG8ga2VlcCB0cmFjayBvZiBib3RoIG91ciBwcmUtcHJvY2Vzc2luZyBzdGVwcyBhbmQgb3VyIG1vZGVsIHNwZWNpZmljYXRpb24uIEl0IGFsc28gYWxsb3dzIHVzIHRvIGltcGxlbWVudCBmYW5jaWVyIG9wdGltaXphdGlvbnMgaW4gYW4gYXV0b21hdGVkIHdheSBhbmQgaXQgY2FuIGFsc28gaGFuZGxlIHBvc3QtcHJvY2Vzc2luZyBvcGVyYXRpb25zLiAKCgpXZSBiZWdpbiBieSBjcmVhdGluZyBhIHdvcmtmbG93IHVzaW5nIHRoZSBgd29ya2Zsb3coKWAgZnVuY3Rpb24gaW4gdGhlIGB3b3JrZmxvd3NgIHBhY2thZ2UuIAoKTmV4dCwgd2UgdXNlIGBhZGRfcmVjaXBlKClgIChvdXIgcHJlLXByb2Nlc3Npbmcgc3BlY2lmaWNhdGlvbnMpIGFuZCB3ZSBhZGQgb3VyIG1vZGVsIHdpdGggdGhlIGBhZGRfbW9kZWwoKWAgZnVuY3Rpb24gLS0gYm90aCBmdW5jdGlvbnMgZnJvbSB0aGUgYHdvcmtmbG93c2AgcGFja2FnZS4KCioqTm90ZSoqOiBXZSBkbyBub3QgbmVlZCB0byBhY3R1YWxseSBgcHJlcCgpYCBvdXIgcmVjaXBlIGJlZm9yZSB1c2luZyB3b3JrZmxvd3MhCgpJZiB5b3UgcmVjYWxsIGBub3ZlbF9yZWNgIGlzIHRoZSByZWNpcGUgd2UgcHJldmlvdXNseSBjcmVhdGVkIHdpdGggdGhlIGByZWNpcGVzYCBwYWNrYWdlIGFuZCBgbG1fUE1fbW9kZWxgIHdhcyBjcmVhdGVkIHdoZW4gd2Ugc3BlY2lmaWVkIG91ciBtb2RlbCB3aXRoIHRoZSBgcGFyc25pcGAgcGFja2FnZS4KSGVyZSwgd2UgY29tYmluZSBldmVyeXRoaW5nIHRvZ2V0aGVyIGludG8gYSB3b3JrZmxvdy4gCgpgYGB7cn0KUE1fd2Zsb3cgPC13b3JrZmxvd3M6OndvcmtmbG93KCkgJT4lCiAgICAgICAgICAgd29ya2Zsb3dzOjphZGRfcmVjaXBlKG5vdmVsX3JlYykgJT4lCiAgICAgICAgICAgd29ya2Zsb3dzOjphZGRfbW9kZWwobG1fUE1fbW9kZWwpClBNX3dmbG93CmBgYAoKQWgsIG5pY2UuIApOb3RpY2UgaG93IGl0IHRlbGxzIHVzIGFib3V0IGJvdGggb3VyIHByZS1wcm9jZXNzaW5nIHN0ZXBzIGFuZCBvdXIgbW9kZWwgc3BlY2lmaWNhdGlvbnMuCgpOZXh0LCB3ZSAicHJlcGFyZSB0aGUgcmVjaXBlIiAob3IgZXN0aW1hdGUgdGhlIHBhcmFtZXRlcnMpIGFuZCBmaXQgdGhlIG1vZGVsIHRvIG91ciB0cmFpbmluZyBkYXRhIGFsbCBhdCBvbmNlLiAKUHJpbnRpbmcgdGhlIG91dHB1dCwgd2UgY2FuIHNlZSB0aGUgY29lZmZpY2llbnRzIG9mIHRoZSBtb2RlbC4KCmBgYHtyfQpQTV93Zmxvd19maXQgPC0gcGFyc25pcDo6Zml0KFBNX3dmbG93LCBkYXRhID0gdHJhaW5fcG0pClBNX3dmbG93X2ZpdApgYGAKCgo8ZGV0YWlscz48c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byBzZWUgdGhlIHN0ZXBzIHRoYXQgdGhlIGB3b3JrZmxvd3NgIHBhY2thZ2UgcGVyZm9ybXMgdGhhdCB1c2VkIHRvIGJlIHJlcXVpcmVkIDwvc3VtbWFyeT4KClByZXZpb3VzbHksIHRoZSBwcm9jZXNzZWQgdHJhaW5pbmcgZGF0YSAoYGJha2VkX3RyYWluYCksIGFzIG9wcG9zZWQgdG8gdGhlIHJhdyB0cmFpbmluZyBkYXRhLCB3b3VsZCBiZSByZXF1aXJlZCB0byBmaXQgdGhlIG1vZGVsLgoKSW4gdGhpcyBjYXNlLCB3ZSB3b3VsZCBhY3R1YWxseSBhbHNvIG5lZWQgdG8gd3JpdGUgdGhlIG1vZGVsIGFnYWluISAKUmVjYWxsIHRoYXQgYGlkYCBhbmQgYGZpcHNgIGFyZSBJRCB2YXJpYWJsZXMgYW5kIHRoYXQgYHZhbHVlc2AgaXMgb3VyIG91dGNvbWUgb2YgaW50ZXJlc3QgKHRoZSBhaXIgcG9sbHV0aW9uIG1lYXN1cmUgYXQgZWFjaCBtb25pdG9yKS4gSXQgaXMgbmljZSB0aGF0IGB3b3JrZmxvd3NgIGtlZXBzIHRyYWNrIG9mIHRoaXMhCgpgYGB7cn0KYmFrZWRfdHJhaW5fcmVhZHkgPC0gYmFrZWRfdHJhaW4gJT4lIAogIHNlbGVjdCgtaWQsIC1maXBzKQoKUE1fZml0IDwtIGxtX1BNX21vZGVsICU+JSAKICBwYXJzbmlwOjpmaXQodmFsdWUgfi4sIGRhdGEgPSBiYWtlZF90cmFpbl9yZWFkeSkKYGBgCgo8L2RldGFpbHM+CgojIyBBc3Nlc3NpbmcgdGhlIG1vZGVsIGZpdAoKQWZ0ZXIgd2UgZml0IG91ciBtb2RlbCwgd2UgY2FuIHVzZSB0aGUgYGJyb29tYCBwYWNrYWdlIHRvIGxvb2sgYXQgdGhlIG91dHB1dCBmcm9tIHRoZSBmaXR0ZWQgbW9kZWwgaW4gYW4gZWFzeS90aWR5IHdheS4gICAKClRoZSBgdGlkeSgpYCBmdW5jdGlvbiByZXR1cm5zIGEgdGlkeSBkYXRhIGZyYW1lIHdpdGggY29lZmZpY2llbnRzIGZyb20gdGhlIG1vZGVsIChvbmUgcm93IHBlciBjb2VmZmljaWVudCkuCgpNYW55IG90aGVyIGBicm9vbWAgZnVuY3Rpb25zIGN1cnJlbnRseSBvbmx5IHdvcmsgd2l0aCBgcGFyc25pcGAgb2JqZWN0cywgbm90IHJhdyBgd29ya2Zsb3dzYCBvYmplY3RzLiAKCkhvd2V2ZXIsIHdlIGNhbiB1c2UgdGhlIGB0aWR5YCBmdW5jdGlvbiBpZiB3ZSBmaXJzdCB1c2UgdGhlIGBwdWxsX3dvcmtmbG93X2ZpdCgpYCBmdW5jdGlvbi4KCmBgYHtyfQp3Zmxvd291dHB1dCA8LSBQTV93Zmxvd19maXQgJT4lIAogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lIAogIGJyb29tOjp0aWR5KCkgCmBgYAoKCmBgYHtyfQp3Zmxvd291dHB1dApgYGAKCldlIGhhdmUgZml0IG91ciBtb2RlbCBvbiBvdXIgdHJhaW5pbmcgZGF0YSwgd2hpY2ggbWVhbnMgd2UgaGF2ZSBjcmVhdGVkIGEgbW9kZWwgdG8gcHJlZGljdCB2YWx1ZXMgb2YgYWlyIHBvbGx1dGlvbiBiYXNlZCBvbiB0aGUgcHJlZGljdG9ycyB0aGF0IHdlIGhhdmUgaW5jbHVkZWQuIFlheSEKCk9uZSBsYXN0IHRoaW5nIGJlZm9yZSB3ZSBsZWF2ZSB0aGlzIHNlY3Rpb24uIApXZSBvZnRlbiBhcmUgaW50ZXJlc3RlZCBpbiBnZXR0aW5nIGEgc2Vuc2Ugb2Ygd2hpY2ggdmFyaWFibGVzIGFyZSB0aGUgbW9zdCBpbXBvcnRhbnQgaW4gb3VyIG1vZGVsLiAKV2UgY2FuIGV4cGxvcmUgdGhlIHZhcmlhYmxlIGltcG9ydGFuY2UgdXNpbmcgdGhlIGB2aXAoKWAgZnVuY3Rpb24gb2YgdGhlIGB2aXBgIHBhY2thZ2UuIApUaGlzIGZ1bmN0aW9uIGNyZWF0ZXMgYSBiYXIgcGxvdCBvZiB2YXJpYWJsZSBpbXBvcnRhbmNlIHNjb3JlcyBmb3IgZWFjaCBwcmVkaWN0b3IgdmFyaWFibGUgKG9yIGZlYXR1cmUpIGluIGEgbW9kZWwuIApUaGUgYmFyIHBsb3QgaXMgb3JkZXJlZCBieSBpbXBvcnRhbmNlIChoaWdoZXN0IHRvIHNtYWxsZXN0KS4gCgoKTm90aWNlIGFnYWluIHRoYXQgd2UgbmVlZCB0byB1c2UgdGhlIGBwdWxsX3dvcmtmbG93X2ZpdCgpYCBmdW5jdGlvbi4KCkxldCdzIHRha2UgYSBsb29rIGF0IHRoZSB0b3AgMTAgY29udHJpYnV0aW5nIHZhcmlhYmxlczoKCmBgYHtyfQpQTV93Zmxvd19maXQgJT4lIAogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lIAogIHZpcChudW1fZmVhdHVyZXMgPSAxMCkKYGBgCgpUaGUgc3RhdGUgaW4gd2hpY2ggdGhlIG1vbml0b3Igd2FzIGxvY2F0ZWQgYW5kIHRoZSBDTUFRIG1vZGVsIGFuZCB0aGUgYW9kIHNhdGVsbGl0ZSBpbmZvcm1hdGlvbiBhcHBlYXIgdG8gYmUgdGhlIG1vc3QgaW1wb3J0YW50IGZvciBwcmVkaWN0aW5nIHRoZSBhaXIgcG9sbHV0aW9uIGF0IGEgZ2l2ZW4gbW9uaXRvci4KCiMjIE1vZGVsIHBlcmZvcm1hbmNlCgpJbiB0aGlzIG5leHQgc2VjdGlvbiwgb3VyIGdvYWwgaXMgdG8gYXNzZXNzIHRoZSBvdmVyYWxsIG1vZGVsIHBlcmZvcm1hbmNlLiAKVGhlIHdheSB3ZSBkbyB0aGlzIGlzIHRvIGNvbXBhcmUgdGhlIHNpbWlsYXJpdHkgYmV0d2VlbiB0aGUgcHJlZGljdGVkIGVzdGltYXRlcyBvZiB0aGUgb3V0Y29tZSB2YXJpYWJsZSBwcm9kdWNlZCBieSB0aGUgbW9kZWwgYW5kIHRoZSB0cnVlIG91dGNvbWUgdmFyaWFibGUgdmFsdWVzLiAKCklmIHlvdSByZWNhbGwgdGhlIFtXaGF0IGlzIG1hY2hpbmUgbGVhcm5pbmc/XSgjd2hhdGlzbWwpIHNlY3Rpb24sIHdlIHNob3dlZCBob3cgdG8gdGhpbmsgYWJvdXQgbWFjaGluZSBsZWFybmluZyAoTUwpIGFzIGFuIG9wdGltaXphdGlvbiBwcm9ibGVtIHRoYXQgdHJpZXMgdG8gbWluaW1pemUgdGhlIGRpc3RhbmNlIGJldHdlZW4gb3VyIHByZWRpY3RlZCBvdXRjb21lICRcaGF0e1l9ID0gZihYKSQgYW5kIGFjdHVhbCBvdXRjb21lICRZJCB1c2luZyBvdXIgZmVhdHVyZXMgKG9yIHByZWRpY3RvciB2YXJpYWJsZXMpICRYJCBhcyBpbnB1dCB0byBhIGZ1bmN0aW9uICRmJCB0aGF0IHdlIHdhbnQgdG8gZXN0aW1hdGUuIAoKJCRkKFkgLSBcaGF0e1l9KSQkCgpBcyBvdXIgZ29hbCBpbiB0aGlzIHNlY3Rpb24gaXMgdG8gYXNzZXNzIG92ZXJhbGwgbW9kZWwgcGVyZm9ybWFuY2UsIHdlIHdpbGwgbm93IHRhbGsgYWJvdXQgZGlmZmVyZW50IGRpc3RhbmNlIG1ldHJpY3MgdGhhdCB5b3UgY2FuIHVzZS4gCgpGaXJzdCwgbGV0J3MgcHVsbCBvdXQgb3VyIHByZWRpY3RlZCBvdXRjb21lIHZhbHVlcyAkXGhhdHtZfSA9IGYoWCkkIGZyb20gdGhlIG1vZGVscyB3ZSBmaXQgKHVzaW5nIGRpZmZlcmVudCBhcHByb2FjaGVzKS4gCgoKYGBge3J9CndmX2ZpdCA8LSBQTV93Zmxvd19maXQgJT4lIAogIHB1bGxfd29ya2Zsb3dfZml0KCkKCndmX2ZpdHRlZF92YWx1ZXMgPC0gZml0dGVkKHdmX2ZpdFtbImZpdCJdXSkKaGVhZCh3Zl9maXR0ZWRfdmFsdWVzKQpgYGAKCkFsdGVybmF0aXZlbHksIHdlIGNhbiBnZXQgdGhlIGZpdHRlZCB2YWx1ZXMgdXNpbmcgdGhlIGBhdWdtZW50KClgIGZ1bmN0aW9uIG9mIHRoZSBgYnJvb21gIHBhY2thZ2UgdXNpbmcgdGhlIG91dHB1dCBmcm9tIGB3b3JrZmxvd3NgOiAKCmBgYHtyfQp3Zl9maXR0ZWRfdmFsdWVzIDwtIAogIGJyb29tOjphdWdtZW50KHdmX2ZpdFtbImZpdCJdXSwgZGF0YSA9IGJha2VkX3RyYWluKSAlPiUgCiAgc2VsZWN0KHZhbHVlLCAuZml0dGVkOi5zdGQucmVzaWQpCgpoZWFkKHdmX2ZpdHRlZF92YWx1ZXMpCgpgYGAKCk5vdGUgdGhhdCBiZWN1YXNlIHdlIHVzZSB0aGUgYWN0dWFsIHdvcmtmbG93IGhlcmUsIHdlIGNhbiAoYW5kIGFjdHVhbGx5IG5lZWQgdG8pIHVzZSB0aGUgcmF3IGRhdGEgaW5zdGVhZCBvZiB0aGUgcHJlLXByb2Nlc3NlZCBkYXRhLgoKYGBge3J9CnZhbHVlc19wcmVkX3RyYWluIDwtIAogIHByZWRpY3QoUE1fd2Zsb3dfZml0LCB0cmFpbl9wbSkgJT4lIAogIGJpbmRfY29scyh0cmFpbl9wbSAlPiUgc2VsZWN0KHZhbHVlLCBmaXBzLCBjb3VudHksIGlkKSkgCgp2YWx1ZXNfcHJlZF90cmFpbgoKYGBgCgojIyMgVmlzdWFsaXppbmcgbW9kZWwgcGVyZm9ybWFuY2UKCk5vdywgd2UgY2FuIGNvbXBhcmUgdGhlIHByZWRpY3RlZCBvdXRjb21lIHZhbHVlcyAob3IgZml0dGVkIHZhbHVlcykgJFxoYXR7WX0kIHRvIHRoZSBhY3R1YWwgb3V0Y29tZSB2YWx1ZXMgJFkkIHRoYXQgd2Ugb2JzZXJ2ZWQ6IAoKYGBge3J9CndmX2ZpdHRlZF92YWx1ZXMgJT4lIAogIGdncGxvdChhZXMoeCA9ICB2YWx1ZSwgeSA9IC5maXR0ZWQpKSArIAogIGdlb21fcG9pbnQoKSArIAogIHhsYWIoImFjdHVhbCBvdXRjb21lIHZhbHVlcyIpICsgCiAgeWxhYigicHJlZGljdGVkIG91dGNvbWUgdmFsdWVzIikKYGBgCgpPSywgc28gb3VyIHJhbmdlIG9mIHRoZSBwcmVkaWN0ZWQgb3V0Y29tZSB2YWx1ZXMgYXBwZWFycyB0byBiZSBzbWFsbGVyIHRoYW4gdGhlIHJlYWwgdmFsdWVzLiAKV2UgY291bGQgcHJvYmFibHkgZG8gYSBiaXQgYmV0dGVyLgoKIyMjIFF1YW50aWZ5aW5nIG1vZGVsIHBlcmZvcm1hbmNlIAoKTmV4dCwgbGV0J3MgdXNlIGRpZmZlcmVudCBkaXN0YW5jZSBmdW5jdGlvbnMgJGQoXGNkb3QpJCB0byBhc3Nlc3MgaG93IGZhciBvZmYgb3VyIHByZWRpY3RlZCBvdXRjb21lICRcaGF0e1l9ID0gZihYKSQgYW5kIGFjdHVhbCBvdXRjb21lICRZJCB2YWx1ZXMgYXJlIGZyb20gZWFjaCBvdGhlcjogCgokJGQoWSAtIFxoYXR7WX0pJCQKCkFzIG1lbnRpb25lZCwgdGhlcmUgYXJlIGVudGlyZSBzY2hvbGFybHkgZmllbGRzIG9mIHJlc2VhcmNoIGRlZGljYXRlZCB0byBpZGVudGlmeWluZyBkaWZmZXJlbnQgZGlzdGFuY2UgbWV0cmljcyAkZChcY2RvdCkkIGZvciBtYWNoaW5lIGxlYXJuaW5nIGFwcGxpY2F0aW9ucy4gCkhvd2V2ZXIsIHdoZW4gcGVyZm9ybWluZyBwcmVkaWN0aW9uIHdpdGggYSBjb250aW51b3VzIG91dGNvbWUgJFkkLCBhIGZldyBvZiB0aGUgbW9zdGx5IGNvbW1vbmx5IHVzZWQgZGlzdGFuY2UgbWV0cmljcyBhcmU6IAoKMS4gbWVhbiBhYnNvbHV0ZSBlcnJvciAoYG1hZWApICAKCiQkTUFFID0gXGZyYWN7XHN1bV97aT0xfV57bn17KHxcaGF0e3lfdH0tIHlfdHwpfV4yfXtufSQkCgoKMi4gUiBzcXVhcmVkIGVycm9yIChgcnNxYCkgLS0gdGhpcyBpcyBhbHNvIGtub3duIGFzIHRoZSBjb2VmZmljaWVudCBvZiBkZXRlcm1pbmF0aW9uIHdoaWNoIGlzIHRoZSBzcXVhcmVkIGNvcnJlbGF0aW9uIGJldHdlZW4gdHJ1dGggYW5kIGVzdGltYXRlCgpUaGlzIGlzIGNhbGN1bGF0ZWQgYW5kIDEgbWludXMgdGhlIGZyYWN0aW9uIG9mIHRoZSByZXNpZHVhbCBzdW0gb2Ygc3F1YXJlcyAoJFNTX3JlcyQpIGJ5IHRoZSB0b3RhbCBzdW0gb2Ygc3F1YXJlcyAoJFNTX3RvdCQpCgoKJCRSU1EgPSBSXjIgPSAxIC0gXGZyYWN7U1NyZXN9e1NTdG90fSQkCgokJFNTX3t0b3R9ID0gXHN1bV97aT0xfV57bn17KHlfaS0gXGJhcnt5fSl9XjIkJApUaGUgdG90YWwgc3VtIG9mIHNxdWFyZXMgaXMgcHJvcG9ydGlvbmFsIHRvIHRoZSB2YXJpYW5jZSBvZiB0aGUgZGF0YS4gSXQgaXMgY2FsY3VsYXRlZCBhcyB0aGUgc3VtIG9mIGVhY2ggIHRydWUgdmFsdWUgZnJvbSB0aGUgbWVhbiB0cnVlIHZhbHVlICgkXGJhcnt5fSQpLgoKJCRTU197cmVzfSA9IFxzdW1fe2k9MX1ee259eyh5X2ktIFxoYXR7eV9pfSl9XjIkJAoKVGhlIHN1bSBvZiBzcXVhcmVzIG9mIHJlc2lkdWFscyBpcyBjYWxjdWxhdGVkIGFzIHRoZSBzdW0gb2YgZWFjaCBwcmVkaWN0ZWQgdmFsdWUgKCRcaGF0e3lfaX0kIG9yIHNvbWV0aW1lcyAkZl9pJCkgZnJvbSB0aGUgdHJ1ZSB2YWx1ZSAoJHlfaSQpLiAKCgozLiBbcm9vdCBtZWFuIHNxdWFyZWQgZXJyb3JdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1Jvb3QtbWVhbi1zcXVhcmVfZGV2aWF0aW9uKXt0YXJnZXQ9Il9ibGFuayJ9IChgcm1zZWApICAgCgokJFJNU0UgPSBcc3FydHtcZnJhY3tcc3VtX3tpPTF9XntufXsoXGhhdHt5X3R9LSB5X3QpfV4yfXtufX0kJAoKCgoKT25lIHdheSB0byBjYWxjdWxhdGUgdGhlc2UgbWV0cmljcyB3aXRoaW4gdGhlIGB0aWR5bW9kZWxzYCBmcmFtZXdvcmsgaXMgdG8gdXNlIHRoZSBgeWFyZHN0aWNrYCBwYWNrYWdlIHVzaW5nIHRoZSBgbWV0cmljcygpYCBmdW5jdGlvbi4gCgpgYGB7cn0KeWFyZHN0aWNrOjptZXRyaWNzKHdmX2ZpdHRlZF92YWx1ZXMsIAogICAgICAgICAgICAgICAgICAgdHJ1dGggPSB2YWx1ZSwgZXN0aW1hdGUgPSAuZml0dGVkKQpgYGAKCkFsdGVybmF0aXZlbHkgaWYgeW91IG9ubHkgd2FudGVkIG9uZSBtZXRyaWMgeW91IGNvdWxkIHVzZSB0aGUgYG1hZSgpYCwgYHJzcSgpYCwgb3IgYHJtc2UoKWAgZnVuY3Rpb25zLCByZXNwZWN0aXZlbHkuIAoKYGBge3J9CnlhcmRzdGljazo6bWFlKHdmX2ZpdHRlZF92YWx1ZXMsIAogICAgICAgICAgICAgICB0cnV0aCA9IHZhbHVlLCBlc3RpbWF0ZSA9IC5maXR0ZWQpCmBgYAoKIyMgQ3Jvc3MgdmFsaWRhdGlvbgoKVW50aWwgbm93IHdlIGhhdmUgdXNlZCBldmVyeXRoaW5nIGluIG91ciAidHJhaW5pbmciIGRhdGFzZXQgKGFuZCBoYXZlIG5vdCB0b3VjaGVkIHRoZSAidGVzdGluZyIgZGF0YXNldCkgZnJvbSB0aGUgYHJzYW1wbGVgIHBhY2thZ2UgdG8gYnVpbGQgb3VyIG1hY2hpbmUgbGVhcm5pbmcgKE1MKSBtb2RlbCAkXGhhdHtZfSA9IGYoWCkkIChvciB0byBlc3RpbWF0ZSAkZiQgdXNpbmcgdGhlIGZlYXR1cmVzIG9yIHByZWRpY3RvciB2YXJpYWJsZSAkWCQpLiAKCkhlcmUsIHdlIHRha2UgbW92ZSB0aGlzIGJleW9uZCB0aGUgc2ltcGxlIHNwbGl0IGludG8gdHJhaW5pbmcgYW5kIHRlc3RpbmcgZGF0YSBzZXRzLiAKV2Ugd2lsbCBhZ2FpbiB1c2UgdGhlIGByc2FtcGxlYCBwYWNrYWdlIGFnYWluIGluIG9yZGVyIHRvIGZ1cnRoZXIgaW1wbGVtZW50IHdoYXQgYXJlIGNhbGxlZCBbY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3MtdmFsaWRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gdGVjaG5pcXVlcy4gVGhpcyBpcyBhbHNvIGNhbGxlZCAqKnJlLXNhbXBsaW5nKiogb3IgKipyZXBhcnRpb25pbmcqKi4gIAoKKipOb3RlKio6IHdlIGFyZSBub3QgYWN0dWFsbHkgZ2V0dGluZyBuZXcgc2FtcGxlcyBmcm9tIHRoZSB1bmRlcmx5aW5nIGRpc3RyaWJ1dGlvbiBzbyB0aGUgdGVybSByZS1zYW1wbGluZyBpcyBhIGJpdCBvZiBhIG1pc25vbWVyLgoKW0Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXZhbGlkYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IHNwbGl0cyBvdXIgdHJhaW5pbmcgZGF0YSBpbnRvIG11bHRpcGxlIHRyYWluaW5nIGRhdGEgc2V0cyB0byBhbGxvdyBmb3IgYSBkZWVwZXIgYXNzZXNzbWVudCBvZiB0aGUgYWNjdXJhY3kgb2YgdGhlIG1vZGVsLgoKSGVyZSBpcyBhIHZpc3VhbGl6YXRpb24gb2YgdGhlIGNvbmNlcHQgZm9yIGNyb3NzIHZhbGlkYXRpb24vcmVzYW1wbGluZy9yZXBhcnRpdGlvbmluZyBmcm9tIFtNYXggS3Vobl0oaHR0cHM6Ly9yZXNvdXJjZXMucnN0dWRpby5jb20vYXV0aG9ycy9tYXgta3Vobil7dGFyZ2V0PSJfYmxhbmsifToKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwicmVzYW1wbGluZy5wbmciKSkKYGBgCgpUZWNobmljYWxseSBjcmVhdGluZyBvdXIgdGVzdGluZyBhbmQgdHJhaW5pbmcgc2V0IG91dCBvZiBvdXIgb3JpZ2luYWwgdHJhaW5pbmcgZGF0YSBpcyBzb21ldGltZXMgY29uc2lkZXJlZCBhIGZvcm0gb2YgW2Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXZhbGlkYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9LCBjYWxsZWQgdGhlIGhvbGRvdXQgbWV0aG9kLiAKVGhlIHJlYXNvbiB3ZSBkbyB0aGlzIGl0IHNvIHdlIGNhbiBnZXQgYSBiZXR0ZXIgc2Vuc2Ugb2YgdGhlIGFjY3VyYWN5IG9mIG91ciBtb2RlbCB1c2luZyBkYXRhIHRoYXQgd2UgZGlkIG5vdCB0cmFpbiBpdCBvbi4gCgpIb3dldmVyLCB3ZSBjYW4gYWN0dWFsbHkgZG8gYSBiZXR0ZXIgam9iIG9mIG9wdGltaXppbmcgb3VyIG1vZGVsIGZvciBhY2N1cmFjeSBpZiB3ZSBhbHNvIHBlcmZvcm0gYW5vdGhlciB0eXBlIG9mIFtjcm9zcyB2YWxpZGF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Dcm9zcy12YWxpZGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSBvbiB0aGUgbmV3bHkgZGVmaW5lZCB0cmFpbmluZyBzZXQgdGhhdCB3ZSBqdXN0IGNyZWF0ZWQuIApUaGVyZSBhcmUgbWFueSBbY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3MtdmFsaWRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gbWV0aG9kcyBhbmQgbW9zdCBjYW4gYmUgZWFzaWx5IGltcGxlbWVudGVkIHVzaW5nIGByc2FtcGxlYCBwYWNrYWdlLiAKSGVyZSwgd2Ugd2lsbCB1c2UgYSB2ZXJ5IHBvcHVsYXIgbWV0aG9kIGNhbGxlZCBlaXRoZXIgW2stZm9sZCBvciB2LWZvbGQgY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly9tYWNoaW5lbGVhcm5pbmdtYXN0ZXJ5LmNvbS9rLWZvbGQtY3Jvc3MtdmFsaWRhdGlvbi8pe3RhcmdldD0iX2JsYW5rIn0uIAoKVGhpcyBtZXRob2QgaW52b2x2ZXMgZXNzZW50aWFsbHkgcHJlZm9ybWluZyB0aGUgaG9sZCBvdXQgbWV0aG9kIGl0ZXJhdGl2ZWx5IHdpdGggdGhlIHRyYWluaW5nIGRhdGEuIAoKRmlyc3QsIHRoZSB0cmFpbmluZyBzZXQgaXMgZGl2aWRlZCBpbnRvICR2JCAob3Igb2Z0ZW4gY2FsbGVkIGNhbGxlZCAkayQpIGVxdWFsbHkgc2l6ZWQgc21hbGxlciBwaWVjZXMuIAoKTmV4dCwgdGhlIG1vZGVsIGlzIHRyYWluZWQgb24gdGhlIG1vZGVsIG9uICR2JC0xIHN1YnNldHMgb2YgdGhlIGRhdGEgaXRlcmF0aXZlbHkgKHJlbW92aW5nIGEgZGlmZmVyZW50ICR2JCB1bnRpbCBhbGwgcG9zc2libGUgJHYkLTEgc2V0cyBoYXZlIGJlZW4gZXZhbHVhdGVkKSB0byBnZXQgYSBzZW5zZSBvZiB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIG1vZGVsLiAKVGhpcyBpcyByZWFsbHkgdXNlZnVsIGZvciBmaW5lIHR1bmluZyBzcGVjaWZpYyBhc3BlY3RzIG9mIHRoZSBtb2RlbCBpbiBhIHByb2Nlc3MgY2FsbGVkIG1vZGVsIHR1bmluZywgd2hpY2ggd2Ugd2lsbCBsZWFybiBhYm91dCBpbiB0aGUgbmV4dCBzZWN0aW9uLiAKCkhlcmUgaXMgYSB2aXN1YWxpemF0aW9uIG9mIGhvdyB0aGUgZm9sZHMgYXJlIGNyZWF0ZWQ6CgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJ2Zm9sZC5wbmciKSkKYGBgCgoqKk5vdGUqKjogUGVvcGxlIHR5cGljYWxseSBpZ25vcmUgc3BhdGlhbCBkZXBlbmRlbmNlIHdpdGggY3Jvc3MgdmFsaWRhdGlvbiBvZiBhaXIgcG9sbHV0aW9uIG1vbml0b3JpbmcgZGF0YSBpbiB0aGUgYWlyIHBvbGx1dGlvbiBmaWVsZCwgc28gd2Ugd2lsbCBkbyB0aGUgc2FtZS4gIEhvd2V2ZXIsIGl0IG1pZ2h0IG1ha2Ugc2Vuc2UgdG8gbGVhdmUgb3V0IGJsb2NrcyBvZiBtb25pdG9ycyByYXRoZXIgdGhhbiAgcmFuZG9tIGluZGl2aWR1YWwgbW9uaXRvcnMgdG8gaGVscCBhY2NvdW50IGZvciBzb21lIHNwYXRpYWwgZGVwZW5kZW5jZS4KCiMjIyBDcmVhdGluZyB0aGUgJHYkLWZvbGRzIHVzaW5nIGByc2FtcGxlYAoKVGhlIFtgdmZvbGRfY3YoKWBdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcnNhbXBsZS9yZWZlcmVuY2UvdmZvbGRfY3YuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBmdW5jdGlvbiBvZiB0aGUgYHJzYW1wbGVgIHBhY2thZ2UgY2FuIGJlIHVzZWQgdG8gcGFyc2UgdGhlIHRyYWluaW5nIGRhdGEgaW50byBmb2xkcyBmb3IgJHYkLWZvbGQgY3Jvc3MgdmFsaWRhdGlvbi4KCi0gVGhlIGB2YCBhcmd1bWVudCBzcGVjaWZpZXMgdGhlIG51bWJlciBvZiBmb2xkcyB0byBjcmVhdGUuCi0gVGhlIGByZXBlYXRzYCBhcmd1bWVudCBzcGVjaWZpZXMgaWYgYW55IHNhbXBsZXMgc2hvdWxkIGJlIHJlcGVhdGVkIGFjcm9zcyBmb2xkcyAtIGRlZmF1bHQgaXMgYEZBTFNFYAotIFRoZSBgc3RyYXRhYCBhcmd1bWVudCBzcGVjaWZpZXMgYSB2YXJpYWJsZSB0byBzdHJhdGlmeSBzYW1wbGVzIGFjcm9zcyBmb2xkcyAtIGp1c3QgbGlrZSBpbiBgaW5pdGlhbF9zcGxpdCgpYC4KCkFnYWluLCBiZWNhdXNlIHRoZXNlIGFyZSBjcmVhdGVkIGF0IHJhbmRvbSwgd2UgbmVlZCB0byB1c2UgdGhlIGJhc2UgYHNldC5zZWVkKClgIGZ1bmN0aW9uIGluIG9yZGVyIHRvIG9idGFpbiB0aGUgc2FtZSByZXN1bHRzIGVhY2ggdGltZSB3ZSBrbml0IHRoaXMgZG9jdW1lbnQuIApHZW5lcmFsbHkgc3BlYWtpbmcgdXNpbmcgMTAgZm9sZHMgaXMgZ29vZCBwcmFjdGljZSwgYnV0IHRoaXMgZGVwZW5kcyBvbiB0aGUgdmFyaWFiaWxpdHkgd2l0aGluIHlvdXIgZGF0YS4gCldlIGFyZSBnb2luZyB0byB1c2UgNCBmb3IgdGhlIHNha2Ugb2YgZXhwZWRpZW5jeS4gCgpgYGB7cn0Kc2V0LnNlZWQoMTIzNCkKdmZvbGRfcG0gPC0gcnNhbXBsZTo6dmZvbGRfY3YoZGF0YSA9IHRyYWluX3BtLCB2ID0gNCkKdmZvbGRfcG0KcHVsbCh2Zm9sZF9wbSwgc3BsaXRzKQpgYGAKCk5vdyB3ZSBjYW4gc2VlIHRoYXQgd2UgaGF2ZSBjcmVhdGVkIDQgZm9sZHMgb2YgdGhlIGRhdGEgYW5kIHdlIGNhbiBzZWUgaG93IG1hbnkgdmFsdWVzIHdlcmUgc2V0IGFzaWRlIGZvciB0ZXN0aW5nIChjYWxsZWQgYXNzZXNzaW5nIGZvciBjcm9zcyB2YWxpZGF0aW9uIHNldHMpIGFuZCB0cmFpbmluZyAoY2FsbGVkIGFuYWx5c2lzIGZvciBjcm9zcyB2YWxpZGF0aW9uIHNldHMpIHdpdGhpbiBlYWNoIGZvbGQuCgpPbmNlIHRoZSBmb2xkcyBhcmUgY3JlYXRlZCB0aGV5IGNhbiBiZSB1c2VkIHRvIGV2YWx1YXRlIHBlcmZvcm1hbmNlIGJ5IGZpdHRpbmcgdGhlIG1vZGVsIHRvIGVhY2ggb2YgdGhlIHJlLXNhbXBsZXMgdGhhdCB3ZSBjcmVhdGVkOgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiY3Jvc3NfdmFsaWRhdGlvbi5wbmciKSkKYGBgCgojIyMgQXNzZXNzaW5nIG1vZGVsIHBlcmZvcm1hbmNlIG9uICR2JC1mb2xkcyB1c2luZyBgdHVuZWAKCldlIGNhbiBmaXQgdGhlIG1vZGVsIHRvIG91ciBjcm9zcyB2YWxpZGF0aW9uIGZvbGRzIHVzaW5nIHRoZSBgZml0X3Jlc2FtcGxlcygpYCBmdW5jdGlvbiBvZiB0aGUgYHR1bmVgIHBhY2thZ2UsIGJ5IHNwZWNpZnlpbmcgb3VyIGB3b3JrZmxvd2Agb2JqZWN0IGFuZCB0aGUgY3Jvc3MgdmFsaWRhdGlvbiBmb2xkIG9iamVjdCB3ZSBqdXN0IGNyZWF0ZWQuIApTZWUgW2hlcmVdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vdHVuZS9yZWZlcmVuY2UvZml0X3Jlc2FtcGxlcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGluZm9ybWF0aW9uLgoKCmBgYHtyfQpyZXNhbXBsZV9maXQgPC0gdHVuZTo6Zml0X3Jlc2FtcGxlcyhQTV93ZmxvdywgdmZvbGRfcG0pCmBgYAoKV2UgY2FuIG5vdyB0YWtlIGEgbG9vayBhdCB2YXJpb3VzIHBlcmZvcm1hbmNlIG1ldHJpY3MgYmFzZWQgb24gdGhlIGZpdCBvZiBvdXIgY3Jvc3MgdmFsaWRhdGlvbiAicmVzYW1wbGVzIi4gClRvIGRvIHRoaXMgd2Ugd2lsbCB1c2UgdGhlIGBzaG93X2Jlc3QoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlLgoKYGBge3J9CnR1bmU6OnNob3dfYmVzdChyZXNhbXBsZV9maXQsIG1ldHJpYyA9ICJybXNlIikKYGBgCgpIZXJlIHdlIGNhbiBzZWUgdGhlIG1lYW4gYFJNU0VgIHZhbHVlIGFjcm9zcyBhbGwgZm91ciBmb2xkcy4gVGhlIGZ1bmN0aW9uIGlzIGNhbGxlZCBgc2hvd19iZXN0KClgIGJlY2F1c2UgaXQgaXMgYWxzbyB1c2VkIGZvciBtb2RlbCB0dW5pbmcgYW5kIGl0IHdpbGwgc2hvdyB0aGUgcGFyYW1ldGVyIGNvbWJpbmF0aW9uIHdpdGggdGhlIGJlc3QgcGVyZm9ybWFuY2UsIHdlIHdpbGwgZGlzY3VzcyB0aGlzIG1vcmUgbGF0ZXIgaW4gdGhlIGNhc2Ugc3R1ZHkuCgoKIyAqKkRhdGEgQW5hbHlzaXMqKgoqKioKCkluIHRoZSBwcmV2aW91cyBzZWN0aW9uLCB3ZSBkZW1vbnN0cmF0ZWQgaG93IHRvIGJ1aWxkIGEgbWFjaGluZSBsZWFybmluZyBtb2RlbCAoc3BlY2lmaWNhbGx5IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwpIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbiB3aXRoIHRoZSBgdGlkeW1vZGVsc2AgZnJhbWV3b3JrLiAKCkluIHRoZSBuZXh0IGZldyBzZWN0aW9uLCB3ZSB3aWxsIGRlbW9uc3RyYXRlIGFub3RoZXIgbWFjaGluZSBsZWFybmluZyBtb2RlbC4gCgoKIyMgUmFuZG9tIEZvcmVzdAoKTm93LCB3ZSBhcmUgZ29pbmcgdG8gcHJlZGljdCBvdXIgb3V0Y29tZSB2YXJpYWJsZSAoYWlyIHBvbGx1dGlvbikgdXNpbmcgYSBkZWNpc2lvbiB0cmVlIG1ldGhvZCBjYWxsZWQgW3JhbmRvbSBmb3Jlc3RdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1JhbmRvbV9mb3Jlc3Qpe3RhcmdldD0iX2JsYW5rIn0uCgpBIFtkZWNpc2lvbiB0cmVlXShodHRwczovL21lZGl1bS5jb20vZ3JleWF0b20vZGVjaXNpb24tdHJlZXMtYS1zaW1wbGUtd2F5LXRvLXZpc3VhbGl6ZS1hLWRlY2lzaW9uLWRjNTA2YTQwM2FlYil7dGFyZ2V0PSJfYmxhbmsifSBpcyBhIHRvb2wgdG8gcGFydGl0aW9uIGRhdGEgb3IgYW55dGhpbmcgcmVhbGx5LCBiYXNlZCBvbiBhIHNlcmllcyBvZiBzZXF1ZW50aWFsIChvZnRlbiBiaW5hcnkpIGRlY2lzaW9ucywgd2hlcmUgdGhlIGRlY2lzaW9ucyBhcmUgY2hvc2VuIGJhc2VkIG9uIHRoZWlyIGFiaWxpdHkgdG8gb3B0aW1hbGx5IHNwbGl0IHRoZSBkYXRhLgoKSGVyZSB5b3UgY2FuIHNlZSBhIHNpbXBsZSBleGFtcGxlOgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vbWlyby5tZWRpdW0uY29tL21heC8xMDAwLzEqTE1vSm1YQ3NRbGNpR1RFeW9TTjM5Zy5qcGVnIikKYGBgCgojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS91bmRlcnN0YW5kaW5nLXJhbmRvbS1mb3Jlc3QtNTgzODFlMDYwMmQyKXt0YXJnZXQ9Il9ibGFuayJ9CgpJbiB0aGUgY2FzZSBvZiBbcmFuZG9tIGZvcmVzdF0oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL2RlY2lzaW9uLXRyZWUtZW5zZW1ibGVzLWJhZ2dpbmctYW5kLWJvb3N0aW5nLTI2NmE4YmE2MGZkOSl7dGFyZ2V0PSJfYmxhbmsifSwgbXVsdGlwbGUgZGVjaXNpb24gdHJlZXMgYXJlIGNyZWF0ZWQgLSBoZW5jZSB0aGUgbmFtZSBmb3Jlc3QsIGFuZCBlYWNoIHRyZWUgaXMgYnVpbHQgdXNpbmcgYSByYW5kb20gc3Vic2V0IG9mIHRoZSB0cmFpbmluZyBkYXRhICh3aXRoIHJlcGxhY2VtZW50KSAtIGhlbmNlIHRoZSBmdWxsIG5hbWUgcmFuZG9tIGZvcmVzdC4gVGhpcyByYW5kb20gYXNwZWN0IGhlbHBzIHRvIGtlZXAgdGhlIGFsZ29yaXRobSBmcm9tIG92ZXJmaXR0aW5nIHRoZSBkYXRhLgoKVGhlIG1lYW4gb2YgdGhlIHByZWRpY3Rpb25zIGZyb20gZWFjaCBvZiB0aGUgdHJlZXMgaXMgdXNlZCBpbiB0aGUgZmluYWwgb3V0cHV0LgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vbWlyby5tZWRpdW0uY29tL21heC8xNDAwLzAqZl9xUVBGcGRvZldHTFFxYy5wbmciKQpgYGAKCgpJbiBvdXIgY2FzZSwgd2UgYXJlIGdvaW5nIHRvIHVzZSB0aGUgcmFuZG9tIGZvcmVzdCBtZXRob2Qgb2YgdGhlIHRoZSBgcmFuZG9tRm9yZXN0YCBwYWNrYWdlLiAKClRoaXMgcGFja2FnZSBpcyBjdXJyZW50bHkgbm90IGNvbXBhdGlibGUgd2l0aCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgdGhhdCBoYXZlIG1vcmUgdGhhbiA1MyBsZXZlbHMuIFNlZSBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JhbmRvbUZvcmVzdC9ORVdTKSBmb3IgdGhlIGRvY3VtZW50YXRpb24gYWJvdXQgd2hlbiB0aGlzIHdhcyB1cGRhdGVkIGZyb20gMjUgbGV2ZWxzLiBUaHVzIHdlIHdpbGwgcmVtb3ZlIHRoZSBgemN0YWAgIGFuZCBgY291bnR5YCB2YXJpYWJsZXMuCgpOb3RlIHRoYXQgdGhlIGBzdGVwX25vdmVsKClgIGZ1bmN0aW9uIGlzIG5lY2Vzc2FyeSBoZXJlIGZvciB0aGUgYHN0YXRlYCB2YXJpYWJsZSB0byBnZXQgYWxsIGNyb3NzIHZhbGlkYXRpb24gZm9sZHMgdG8gd29yaywgYmVjYXVzZSB0aGVyZSB3aWxsIGJlIGRpZmZlcmVudCBsZXZlbHMgaW5jbHVkZWQgaW4gZWFjaCBmb2xkIHRlc3QgYW5kIHRyYWluaW5nIHNldHMuIFRoZSBuZXcgbGV2ZWxzIGZvciBzb21lIG9mIHRoZSB0ZXN0IHNldHMgd291bGQgb3RoZXJ3aXNlIHJlc3VsdCBpbiBhbiBlcnJvci4KCkFjY29yZGluZyB0byB0aGUgW2RvY3VtZW50YXRpb25dKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy9yZWNpcGVzL3ZlcnNpb25zLzAuMS4xMy90b3BpY3Mvc3RlcF9ub3ZlbCkgZm9yIHRoZSBgcmVjaXBlc2AgcGFja2FnZToKCj4gc3RlcF9ub3ZlbCBjcmVhdGVzIGEgc3BlY2lmaWNhdGlvbiBvZiBhIHJlY2lwZSBzdGVwIHRoYXQgd2lsbCBhc3NpZ24gYSBwcmV2aW91c2x5IHVuc2VlbiBmYWN0b3IgbGV2ZWwgdG8gYSBuZXcgdmFsdWUuCgpgYGB7cn0KUkZfcmVjIDwtIHJlY2lwZSh0cmFpbl9wbSkgJT4lCiAgICB1cGRhdGVfcm9sZShldmVyeXRoaW5nKCksIG5ld19yb2xlID0gInByZWRpY3RvciIpJT4lCiAgICB1cGRhdGVfcm9sZSh2YWx1ZSwgbmV3X3JvbGUgPSAib3V0Y29tZSIpJT4lCiAgICB1cGRhdGVfcm9sZShpZCwgbmV3X3JvbGUgPSAiaWQgdmFyaWFibGUiKSAlPiUKICAgIHVwZGF0ZV9yb2xlKCJmaXBzIiwgbmV3X3JvbGUgPSAiY291bnR5IGlkIikgJT4lCiAgICBzdGVwX25vdmVsKCJzdGF0ZSIpICU+JQogICAgc3RlcF9zdHJpbmcyZmFjdG9yKCJzdGF0ZSIsICJjb3VudHkiLCAiY2l0eSIpICU+JQogICAgc3RlcF9ybSgiY291bnR5IikgJT4lCiAgICBzdGVwX3JtKCJ6Y3RhIikgJT4lCiAgICBzdGVwX2NvcnIoYWxsX251bWVyaWMoKSklPiUKICAgIHN0ZXBfbnp2KGFsbF9udW1lcmljKCkpCmBgYAoKVGhlIGByYW5kX2ZvcmVzdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHBhcnNuaXBgIHBhY2thZ2UgaGFzIHRocmVlIGltcG9ydGFudCBhcmd1bWVudHMgdGhhdCBhY3QgYXMgYW4gaW50ZXJmYWNlIGZvciB0aGUgZGlmZmVyZW50IHBvc3NpYmxlIGVuZ2luZXMgdG8gcGVyZm9ybSBhIHJhbmRvbSBmb3Jlc3QgYW5hbHlzaXM6CgoxLiBgbXRyeWAgLSBUaGUgbnVtYmVyIG9mIHByZWRpY3RvciB2YXJpYWJsZXMgKG9yIGZlYXR1cmVzKSB0aGF0IHdpbGwgYmUgcmFuZG9tbHkgc2FtcGxlZCBhdCBlYWNoIHNwbGl0IHdoZW4gY3JlYXRpbmcgdGhlIHRyZWUgbW9kZWxzLiBUaGUgZGVmYXVsdCBudW1iZXIgZm9yIHJlZ3Jlc3Npb24gYW5hbHlzZXMgaXMgdGhlIG51bWJlciBvZiBwcmVkaWN0b3JzIGRpdmlkZWQgYnkgMy4gCjIuIGBtaW5fbmAgLSBUaGUgbWluaW11bSBudW1iZXIgb2YgZGF0YSBwb2ludHMgaW4gYSBub2RlIHRoYXQgYXJlIHJlcXVpcmVkIGZvciB0aGUgbm9kZSB0byBiZSBzcGxpdCBmdXJ0aGVyLgozLiBgdHJlZXNgIC0gdGhlIG51bWJlciBvZiB0cmVlcyBpbiB0aGUgZW5zZW1ibGUKCldlIHdpbGwgc3RhcnQgYnkgdHJ5aW5nIGFuIGBtdHJ5YCB2YWx1ZSBvZiAxMCBhbmQgYSBgbWluX25gIHZhbHVlIG9mIDMuCgpOb3cgdGhhdCB3ZSBoYXZlIG91ciByZWNpcGUgKGBSRl9yZWNgKSwgbGV0J3Mgc3BlY2lmeSB0aGUgbW9kZWwgd2l0aCBgcmFuZF9mb3Jlc3QoKWAgZnJvbSBgcGFyc25pcGAuCgpgYGB7cn0KUE10cmVlX21vZGVsIDwtIAogIHBhcnNuaXA6OnJhbmRfZm9yZXN0KG10cnkgPSAxMCwgbWluX24gPSAzKQpQTXRyZWVfbW9kZWwKYGBgCgpOZXh0LCB3ZSBzZXQgdGhlIGVuZ2luZSBhbmQgbW9kZToKCk5vdGUgdGhhdCB5b3UgY291bGQgYWxzbyB1c2UgdGhlIGByYW5nZXJgIG9yIGBzcGFya2AgcGFja2FnZXMgaW5zdGVhZCBvZiBgcmFuZG9tRm9yZXN0YC4KSWYgeW91IHdlcmUgdG8gdXNlIHRoZSBgcmFuZ2VyYCBwYWNrYWdlIHRvIGltcGxlbWVudCB0aGUgcmFuZG9tIGZvcmVzdCBhbmFseXNpcyB5b3Ugd291bGQgbmVlZCB0byBzcGVjaWZ5IGFuIGBpbXBvcnRhbmNlYCBhcmd1bWVudCB0byBiZSBhYmxlIHRvIGV2YWx1YXRlIHByZWRpY3RvciBpbXBvcnRhbmNlLiAgVGhlIG9wdGlvbnMgYXJlIGBpbXB1cml0eWAgb3IgYHBlcm11dGF0aW9uYC4KClRoZXNlIG90aGVyIHBhY2thZ2VzIGhhdmUgZGlmZmVyZW50IGFkdmFudGFnZXMgYW5kIGRpc2FkdmFudGFnZXMtIGZvciBleGFtcGxlIGByYW5nZXJgIGFuZCBgc3BhcmtgIGFyZSBub3QgYXMgbGltaXRpbmcgZm9yIHRoZSBudW1iZXIgb2YgY2F0ZWdvcmllcyBmb3IgY2F0ZWdvcmljYWwgdmFyaWFibGVzLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBzZWUgdGhlaXIgZG9jdW1lbnRhdGlvbjogW2hlcmVdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yYW5nZXIvcmFuZ2VyLnBkZikgZm9yIHJhbmdlciwgW2hlcmVdKGh0dHA6Ly9zcGFyay5hcGFjaGUub3JnL2RvY3MvbGF0ZXN0L21sbGliLWVuc2VtYmxlcy5odG1sI3JhbmRvbS1mb3Jlc3RzKSBmb3IgYHNwYXJrYCwgYW5kIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmFuZG9tRm9yZXN0L3JhbmRvbUZvcmVzdC5wZGYpIGZvciBgcmFuZG9tRm9yZXN0YC4KClNlZSBbaGVyZV0oaHR0cHM6Ly9wYXJzbmlwLnRpZHltb2RlbHMub3JnL3JlZmVyZW5jZS9yYW5kX2ZvcmVzdC5odG1sKSBmb3IgbW9yZSBkb2N1bWVudGF0aW9uIGFib3V0IGltcGxlbWVudGluZyB0aGVzZSBlbmdpbmUgb3B0aW9ucyB3aXRoIHRpZHltb2RlbHMuIE5vdGUgdGhhdCB0aGVyZSBhcmUgYWxzbyBbb3RoZXJdKGh0dHBzOi8vd3d3LmxpbmtlZGluLmNvbS9wdWxzZS9kaWZmZXJlbnQtcmFuZG9tLWZvcmVzdC1wYWNrYWdlcy1yLW1hZGh1ci1tb2RpLykgUiBwYWNrYWdlcyBmb3IgaW1wbGVtZW50aW5nIHJhbmRvbSBmb3Jlc3QgYWxnb3JpdGhtcywgYnV0IHRoZXNlIHRocmVlIHBhY2thZ2VzIChgcmFuZ2VyYCwgYHNwYXJrYCwgYW5kIGByYW5kb21Gb3Jlc3RgKSBhcmUgY3VycmVudGx5IGNvbXBhdGlibGUgd2l0aCBgdGlkeW1vZGVsc2AuCgpXZSBhbHNvIG5lZWQgdG8gc3BlY2lmeSB3aXRoIHRoZSBgc2V0X21vZGUoKWAgZnVuY3Rpb24gdGhhdCBvdXIgb3V0Y29tZSB2YXJpYWJsZSAoYWlyIHBvbGx1dGlvbikgaXMgY29udGludW91cy4gCgpgYGB7cn0KClJGX1BNX21vZGVsIDwtIAogIFBNdHJlZV9tb2RlbCAlPiUKICBzZXRfZW5naW5lKCJyYW5kb21Gb3Jlc3QiKSAlPiUKICBzZXRfbW9kZSgicmVncmVzc2lvbiIpCgpSRl9QTV9tb2RlbApgYGAKClRoZW4sIHdlIHB1dCB0aGlzIGFsbCB0b2dldGhlciBpbnRvIGEgYHdvcmtmbG93YDogCgojIyMjIHsucmVjYWxsX2NvZGVfcXVlc3Rpb25fYmxvY2t9CjxiPjx1PiBRdWVzdGlvbiBPcHBvcnR1bml0eSA8L3U+PC9iPgoKU2VlIGlmIHlvdSBjYW4gY29tZSB1cCB3aXRoIHRoZSBjb2RlIHRvIGRvIHRoaXMuCgojIyMjCgoqKioKPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHJldmVhbCB0aGUgYW5zd2VyLiA8L3N1bW1hcnk+CgpgYGB7cn0KUkZfd2Zsb3cgPC0gd29ya2Zsb3dzOjp3b3JrZmxvdygpICU+JQogICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9yZWNpcGUoUkZfcmVjKSAlPiUKICAgICAgICAgICAgd29ya2Zsb3dzOjphZGRfbW9kZWwoUkZfUE1fbW9kZWwpCgpgYGAKPC9kZXRhaWxzPiAKKioqCgpgYGB7cn0KUkZfd2Zsb3cKYGBgCgoKRmluYWxseSwgd2UgZml0IHRoZSBkYXRhIHRvIHRoZSBtb2RlbDoKCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpEbyB5b3UgcmVjYWxsIGhvdyB0byBkbyB0aGlzPwoKIyMjIwoKKioqCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byByZXZlYWwgdGhlIGFuc3dlci4gPC9zdW1tYXJ5PgoKYGBge3J9ClJGX3dmbG93X2ZpdCA8LSBwYXJzbmlwOjpmaXQoUkZfd2Zsb3csIGRhdGEgPSB0cmFpbl9wbSkKYGBgCjwvZGV0YWlscz4gCioqKgoKYGBge3J9ClJGX3dmbG93X2ZpdApgYGAKCkxldCdzIHRha2UgYSBsb29rIGF0IHRoZSB0b3AgMTAgY29udHJpYnV0aW5nIHZhcmlhYmxlczoKCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpTZWUgaWYgeW91IGNhbiByZWNhbGwgaG93IHRvIGRvIHRoaXMuCgojIyMjCgpgYGB7ciwgZWNobyA9IEZBTFNFfQpSRl93Zmxvd19maXQgJT4lIAogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lIAogIHZpcChudW1fZmVhdHVyZXMgPSAxMCkKCmBgYAoKCioqKgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBhbnN3ZXIuIDwvc3VtbWFyeT4KCmBgYHtyfQpSRl93Zmxvd19maXQgJT4lIAogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lIAogIHZpcChudW1fZmVhdHVyZXMgPSAxMCkKYGBgCjwvZGV0YWlscz4KKioqCgoKSW50ZXJlc3RpbmchIEluIHRoZSBwcmV2aW91cyBtb2RlbCB0aGUgQ01BUSB2YWx1ZXMgYW5kIHRoZSBzdGF0ZSB3aGVyZSB0aGUgbW9uaXRvciB3YXMgbG9jYXRlZCB3ZXJlIGFsc28gdGhlIHRvcCB0d28gbW9zdCBpbXBvcnRhbnQsIGhvd2V2ZXIgcHJlZGljdG9ycyBhYm91dCBlZHVjYXRpb24gbGV2ZWxzIG9mIHRoZSBjb21tdW5pdGllcyB3aGVyZSB0aGUgbW9uaXRvciB3YXMgbG9jYXRlZCB3YXMgYW1vbmcgdGhlIHRvcCBtb3N0IGltcG9ydGFudC4gTm93IHdlIHNlZSB0aGF0IHBvcHVsYXRpb24gZGVuc2l0eSBhbmQgcHJveGltaXR5IHRvIHNvdXJjZXMgb2YgZW1pc3Npb25zIGFuZCByb2FkcyBhcmUgYW1vbmcgdGhlIHRvcCB0ZW4uCgoKTm93IGxldCdzIHRha2UgYSBsb29rIGF0IG1vZGVsIHBlcmZvcm1hbmNlIGJ5IGZpdHRpbmcgdGhlIGRhdGEgdXNpbmcgY3Jvc3MgdmFsaWRhdGlvbjoKCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpTZWUgaWYgeW91IGNhbiByZWNhbGwgaG93IHRvIGRvIHRoaXMuCgojIyMjCgoqKioKPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHJldmVhbCB0aGUgYW5zd2VyLiA8L3N1bW1hcnk+CgpgYGB7ciwgZXZhbCA9IEZBTFNFfQpzZXQuc2VlZCg0NTYpCnJlc2FtcGxlX1JGX2ZpdCA8LSB0dW5lOjpmaXRfcmVzYW1wbGVzKFJGX3dmbG93LCB2Zm9sZF9wbSkKY29sbGVjdF9tZXRyaWNzKHJlc2FtcGxlX1JGX2ZpdCkKYGBgCgo8L2RldGFpbHM+CioqKgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Kc2V0LnNlZWQoNDU2KQpyZXNhbXBsZV9SRl9maXQgPC0gdHVuZTo6Zml0X3Jlc2FtcGxlcyhSRl93ZmxvdywgdmZvbGRfcG0pCmNvbGxlY3RfbWV0cmljcyhyZXNhbXBsZV9SRl9maXQpCmBgYAoKTm93IGxldCdzIGNvbXBhcmUgdGhlIHBlcmZvcm1hbmNlIG9mIHRoaXMgbW9kZWwgd2l0aCBvdXIgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWw6CgpgYGB7cn0KIyBvdXIgaW5pdGlhbCBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbDoKY29sbGVjdF9tZXRyaWNzKHJlc2FtcGxlX2ZpdCkKYGBgCgpPSywgc28gb3VyIGZpcnN0IG1vZGVsIGhhZCBhIG1lYW4gYHJtc2VgIHZhbHVlIG9mIDIuMTcuCkl0IGxvb2tzIGxpa2UgdGhlIHJhbmRvbSBmb3Jlc3QgbW9kZWwgaGFkICBhIG11Y2ggbG93ZXIgYHJtc2VgIHZhbHVlIG9mIDEuNzIuCgojIyMjIHsudGhpbmtfcXVlc3Rpb25fYmxvY2t9CjxiPjx1PiBRdWVzdGlvbiBPcHBvcnR1bml0eSA8L3U+PC9iPgoKRG8geW91IHJlY2FsbCBob3cgdGhlIFJNU0UgaXMgY2FsY3VsYXRlZD8KCiMjIyMKCioqKgoKPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHJldmVhbCB0aGUgYW5zd2VyLiA8L3N1bW1hcnk+CiQkUk1TRSA9IFxzcXJ0e1xmcmFje1xzdW1fe2k9MX1ee259eyhcaGF0e3lfdH0tIHlfdCl9XjJ9e259fSQkCjwvZGV0YWlscz4gCgpJZiB3ZSB0dW5lZCBvdXIgcmFuZG9tIGZvcmVzdCBtb2RlbCBiYXNlZCBvbiB0aGUgbnVtYmVyIG9mIHRyZWVzIG9yIHRoZSB2YWx1ZSBmb3IgYG10cnlgICh3aGljaCBpcyAiVGhlIG51bWJlciBvZiBwcmVkaWN0b3JzIHRoYXQgd2lsbCBiZSByYW5kb21seSBzYW1wbGVkIGF0IGVhY2ggc3BsaXQgd2hlbiBjcmVhdGluZyB0aGUgdHJlZSBtb2RlbHMiKSwgd2UgbWlnaHQgZ2V0IGEgbW9kZWwgd2l0aCBldmVuIGJldHRlciBwZXJmb3JtYW5jZS4KCkhvd2V2ZXIsIG91ciBjcm9zcyB2YWxpZGF0ZWQgbWVhbiBybXNlIHZhbHVlIG9mIDEuNzIgaXMgcXVpdGUgZ29vZCBiZWNhdXNlIG91ciByYW5nZSBvZiB0cnVlIG91dGNvbWUgdmFsdWVzIGlzIG11Y2ggbGFyZ2VyOiAoYHIgcm91bmQocmFuZ2UodGVzdF9wbSR2YWx1ZSksMylgKS4KCgojIyBNb2RlbCB0dW5pbmcKCltIeXBlcnBhcmFtZXRlcnNdKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vZGlmZmVyZW5jZS1iZXR3ZWVuLWEtcGFyYW1ldGVyLWFuZC1hLWh5cGVycGFyYW1ldGVyLykgYXJlIG9mdGVuIHRoaW5ncyB0aGF0IHdlIG5lZWQgdG8gc3BlY2lmeSBhYm91dCBhIG1vZGVsLiBGb3IgZXhhbXBsZSwgdGhlIG51bWJlciBvZiBwcmVkaWN0b3IgdmFyaWFibGVzIChvciBmZWF0dXJlcykgdGhhdCB3aWxsIGJlIHJhbmRvbWx5IHNhbXBsZWQgYXQgZWFjaCBzcGxpdCB3aGVuIGNyZWF0aW5nIHRoZSB0cmVlIG1vZGVscyBjYWxsZWQgYG10cnlgIGlzIGEgaHlwZXJwYXJhbWV0ZXIuIFRoZSBkZWZhdWx0IG51bWJlciBmb3IgcmVncmVzc2lvbiBhbmFseXNlcyBpcyB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgZGl2aWRlZCBieSAzLiBJbnN0ZWFkIG9mIGFyYml0cmFyaWx5IHNwZWNpZnlpbmcgdGhpcywgd2UgY2FuIHRyeSB0byBkZXRlcm1pbmUgdGhlIGJlc3Qgb3B0aW9uIGZvciBtb2RlbCBwZXJmb3JtYW5jZSBieSBhIHByb2Nlc3MgY2FsbGVkIHR1bmluZy4gCgoKTm93IGxldCdzIHRyeSBzb21lIHR1bmluZy4KCkxldCdzIHRha2UgYSBjbG9zZXIgbG9vayBhdCB0aGUgYG10cnlgIGFuZCBgbWluX25gIGh5cGVycGFyYW1ldHJzIGluIG91ciBSYW5kb20gRm9yZXN0IG1vZGVsLgoKV2UgYXJlbid0IGV4YWN0bHkgc3VyZSB3aGF0IHZhbHVlcyBvZiBgbXRyeWAgYW5kIGBtaW5fbmAgYWNoaWV2ZSBnb29kIGFjY3VyYWN5IHlldCBrZWVwIG91ciBtb2RlbCBnZW5lcmFsaXphYmxlIGZvciBvdGhlciBkYXRhLgoKVGhpcyBpcyB3aGVuIG91ciBjcm9zcyB2YWxpZGF0aW9uIG1ldGhvZHMgYmVjb21lIHJlYWxseSBoYW5keSBiZWNhdXNlIG5vdyB3ZSBjYW4gdGVzdCBvdXQgZGlmZmVyZW50IHZhbHVlcyBmb3IgZWFjaCBvZiB0aGVzZSBoeXBlcnBhcmFtZXRlcnMgdG8gYXNzZXNzIHdoYXQgdmFsdWVzIHNlZW0gdG8gd29yayBiZXN0IGZvciBtb2RlbCBwZXJmb3JtYW5jZSBvbiB0aGVzZSByZXNhbXBsZXMgb2Ygb3VyIHRyYWluaW5nIHNldCBkYXRhLgoKUHJldmlvdXNseSB3ZSBzcGVjaWZpZWQgb3VyIG1vZGVsIGxpa2Ugc286CmBgYHtyfQpSRl9QTV9tb2RlbCA8LSAKICBwYXJzbmlwOjpyYW5kX2ZvcmVzdChtdHJ5ID0gMTAsIG1pbl9uID0gMykgJT4lCiAgc2V0X2VuZ2luZSgicmFuZG9tRm9yZXN0IikgJT4lCiAgc2V0X21vZGUoInJlZ3Jlc3Npb24iKQoKUkZfUE1fbW9kZWwKYGBgCk5vdyBpbnN0ZWFkIG9mIHNwZWNpZnlpbmcgYSB2YWx1ZSBmb3IgdGhlIGBtdHJ5YCBhbmQgYG1pbl9uYCBhcmd1bWVudHMsIHdlIGNhbiB1c2UgdGhlIGB0dW5lKClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZSBsaWtlIHNvOiBgbXRyeSA9IHR1bmUoKWAuIFRoaXMgaW5kaWNhdGVzIHRoYXQgdGhlc2UgaHlwZXJwYXJhbWV0ZXJzIGFyZSB0byBiZSB0dW5lZC4gCgpgYGB7cn0KCnR1bmVfUkZfbW9kZWwgPC0gcmFuZF9mb3Jlc3QobXRyeSA9IHR1bmUoKSwgbWluX24gPSB0dW5lKCkpICU+JQogIHNldF9lbmdpbmUoInJhbmRvbUZvcmVzdCIpICU+JQogIHNldF9tb2RlKCJyZWdyZXNzaW9uIikKICAgIAoKdHVuZV9SRl9tb2RlbAoKYGBgCgoKQWdhaW4gd2Ugd2lsbCBhZGQgdGhpcyB0byBhIHdvcmtmbG93LCB0aGUgb25seSBkaWZmZXJlbmNlIGhlcmUgaXMgdGhhdCB3ZSBhcmUgdXNpbmcgYSBkaWZmZXJlbnQgbW9kZWwgc3BlY2lmaWNhdGlvbiB3aXRoIGB0dW5lX1JGX21vZGVsYCBpbnN0ZWFkIG9mIGBSRl9tb2RlbGA6CgpgYGB7cn0KClJGX3R1bmVfd2Zsb3cgPC0gd29ya2Zsb3dzOjp3b3JrZmxvdygpICU+JQogICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9yZWNpcGUoUkZfcmVjKSAlPiUKICAgICAgICAgICAgd29ya2Zsb3dzOjphZGRfbW9kZWwodHVuZV9SRl9tb2RlbCkKUkZfdHVuZV93ZmxvdwoKYGBgCgoKTm93IHdlIGNhbiB1c2UgdGhlIGB0dW5lX2dyaWQoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlIHRvIGV2YWx1YXRlIGRpZmZlcmVudCBjb21iaW5hdGlvbnMgb2YgdmFsdWVzIGZvciBgbXRyeWAgYW5kIGBtaW5fbmAgdXNpbmcgb3VyIGNyb3NzIHZhbGlkYXRpb24gc2FtcGxlcyBvZiBvdXIgdHJhaW5pbmcgc2V0IChgdmZvbGRfcG1gKSB0byBzZWUgd2hhdCBjb21iaW5hdGlvbiBvZiB2YWx1ZXMgcGVyZm9ybXMgYmVzdC4KClRvIHVzZSB0aGlzIGZ1bmN0aW9uIHdlIHdpbGwgc3BlY2lmeSB0aGUgd29ya2Zsb3cgdXNpbmcgdGhlIGBvYmplY3RgIGFyZ3VtZW50ICBhbmQgdGhlIHNhbXBsZXMgdG8gdXNlIHVzaW5nIHRoZSBgcmVzYW1wbGVzYCBhcmd1bWVudC4gVGhlIGBncmlkYCBhcmd1bWVudCBzcGVjaWZpZXMgaG93IG1hbnkgcG9zc2libGUgb3B0aW9ucyBmb3IgZWFjaCBhcmd1bWVudCBzaG91bGQgYmUgYXR0ZW1wdGVkLgoKQnkgZGVmYXVsdCAxMCBkaWZmZXJlbnQgdmFsdWVzIHdpbGwgYmUgYXR0ZW1wdGVkIGZvciBlYWNoIGh5cGVycGFyYW1ldGVyIHRoYXQgaXMgYmVpbmcgdHVuZWQuCgpXZSBjYW4gdXNlIHRoZSBgZG9QYXJhbGxlbGAgcGFja2FnZSB0byBhbGxvdyB1cyB0byBmaXQgYWxsIHRoZXNlIG1vZGVscyB0byBvdXIgY3Jvc3MgdmFsaWRhdGlvbiBzYW1wbGVzIGZhc3Rlci4gU28gaWYgeW91IHdlcmUgcGVyZm9ybWluZyB0aGlzIG9uIGEgY29tcHV0ZXIgd2l0aCBtdWx0aXBsZSBjb3JlcyBvciBwcm9jZXNzb3JzLCB0aGVuIGRpZmZlcmVudCBtb2RlbHMgd2l0aCBkaWZmZXJlbnQgaHlwZXJwYXJhbWV0ZXIgdmFsdWVzIGNhbiBiZSBmaXQgdG8gdGhlIGNyb3NzIHZhbGlkYXRpb24gc2FtcGxlcyBzaW11bHRhbmVvdXNseSBhY3Jvc3MgZGlmZmVyZW50IGNvcmVzIG9yIHByb2Nlc3NvcnMuIAoKWW91IGNhbiBzZWUgaG93IG1hbnkgY29yZXMgeW91IGhhdmUgYWNjZXNzIHRvIG9uIHlvdXIgc3lzdGVtIHVzaW5nIHRoZSBgZGV0ZWN0Q29yZXMoKWAgZnVuY3Rpb24gaW4gdGhlIGBwYXJhbGxlbGAgcGFja2FnZS4gCgpgYGB7cn0KcGFyYWxsZWw6OmRldGVjdENvcmVzKCkKYGBgCgpUaGUgYHJlZ2lzdGVyRG9QYXJhbGxlbCgpYCBmdW5jdGlvbiB3aWxsIHVzZSB0aGUgbnVtYmVyIGZvciBjb3JlcyBzcGVjaWZpZWQgdXNpbmcgdGhlIGBjb3Jlcz1gIGFyZ3VlbWVudCwgb3IgaXQgd2lsbCBhc3NpZ24gaXQgYXV0b21hdGljYWxseSB0byBvbmUtaGFsZiBvZiB0aGUgbnVtYmVyIG9mIGNvcmVzIGRldGVjdGVkIGJ5IHRoZSBgcGFyYWxsZWxgIHBhY2thZ2UuIAoKV2UgbmVlZCB0byB1c2UgYHNldC5zZWVkKClgIGhlcmUgYmVjYXVzZSB0aGUgdmFsdWVzIGNob3NlbiBmb3IgYG10cnlgIGFuZCBgbWluX25gIG1heSB2YXJ5IGlmIHdlIHByZWZvcm0gdGhpcyBldmFsdWF0aW9uIGFnYWluIGJlY2F1c2UgdGhleSBhcmUgY2hvc2VuIHNlbWktcmFuZG9tbHkgKG1lYW5pbmcgdGhhdCB0aGV5IGFyZSB3aXRoaW4gYSByYW5nZSBvZiByZWFzb25hYmxlIHZhbHVlcyBidXQgc3RpbGwgcmFuZG9tKS4KCk5vdGU6IHRoaXMgc3RlcCB3aWxsIHRha2Ugc29tZSB0aW1lLgoKYGBge3J9CmRvUGFyYWxsZWw6OnJlZ2lzdGVyRG9QYXJhbGxlbChjb3Jlcz0yKQpzZXQuc2VlZCgxMjMpCnR1bmVfUkZfcmVzdWx0cyA8LSB0dW5lX2dyaWQob2JqZWN0ID0gUkZfdHVuZV93ZmxvdywgcmVzYW1wbGVzID0gdmZvbGRfcG0sIGdyaWQgPSAyMCkKdHVuZV9SRl9yZXN1bHRzCmBgYAoKClNlZSBbdGhlIHR1bmUgZ2V0dGluZyBzdGFydGVkIGd1aWRlIF0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby90dW5lL2FydGljbGVzL2dldHRpbmdfc3RhcnRlZC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IGltcGxlbWVudGluZyB0aGlzIGluIGB0aWR5bW9kZWxzYC4KCklmIHlvdSB3YW50ZWQgbW9yZSBjb250cm9sIG92ZXIgdGhpcyBwcm9jZXNzIHlvdSBjb3VsZCBzcGVjaWZ5IGhvdyB0aGUgZGlmZmVyZW50IHBvc3NpYmxlIG9wdGlvbnMgZm9yIGBtdHJ5YCBhbmQgYG1pbl9uYCBpbiB0aGUgYHR1bmVfZ3JpZCgpYCBmdW5jdGlvbiB1c2luZyB0aGUgYGdyaWRfKigpYCBmdW5jdGlvbnMgb2YgdGhlIGBkaWFsc2AgcGFja2FnZSB0byBjcmVhdGUgYSBtb3JlIHNwZWNpZmljIGdyaWQuCgpCZSBkZWZhdWx0IHRoZSB2YWx1ZXMgZm9yIHRoZSBoeXBlcnBhcmFtZXRlcnMgYmVpbmcgdHVuZWQgYXJlIGNob3NlbiBzZW1pLXJhbmRvbWx5IChtZWFuaW5nIHRoYXQgdGhleSBhcmUgd2l0aGluIGEgcmFuZ2Ugb2YgcmVhc29uYWJsZSB2YWx1ZXMgYnV0IHN0aWxsIHJhbmRvbSkuLgoKCk5vdyB3ZSBjYW4gdXNlIHRoZSBgY29sbGVjdF9tZXRyaWNzKClgIGZ1bmN0aW9uIGFnYWluIHRvIHRha2UgYSBsb29rIGF0IHdoYXQgaGFwcGVuZWQgd2l0aCBvdXIgY3Jvc3MgdmFsaWRhdGlvbiB0ZXN0cy4gV2UgY2FuIHNlZSB0aGUgZGlmZmVyZW50IHZhbHVlcyBjaG9zZW4gZm9yIGBtdHJ5YCBhbmQgYG1pbl9uYCBhbmQgdGhlIG1lYW4gcm1zZSBhbmQgcnNxIHZhbHVlcyBhY3Jvc3MgdGhlIGNyb3NzIHZhbGlkYXRpb24gc2FtcGxlcy4KCmBgYHtyfQp0dW5lX1JGX3Jlc3VsdHMlPiUKICBjb2xsZWN0X21ldHJpY3MoKQpgYGAKCldlIGNhbiBub3cgdXNlIHRoZSBgc2hvd19iZXN0KClgIGZ1bmN0aW9uIGFzIGl0IHdhcyB0cnVseSBpbnRlbmRlZCwgdG8gc2VlIHdoYXQgdmFsdWVzIGZvciBgbWluX25gIGFuZCBgbXRyeWAgcmVzdWx0ZWQgaW4gdGhlIGJlc3QgcGVyZm9ybWFuY2UuCgpgYGB7cn0Kc2hvd19iZXN0KHR1bmVfUkZfcmVzdWx0cywgbWV0cmljID0gInJtc2UiLCBuID0xKQpgYGAKVGhlcmUgd2UgaGF2ZSBpdC4uLiBsb29rcyBsaWtlIGFuIGBtdHJ5YCBvZiAxNyBhbmQgYG1pbl9uYCBvZiA0IGhhZCB0aGUgYmVzdCBgcm1zZWAgdmFsdWUuIFlvdSBjYW4gdmVyaWZ5IHRoaXMgaW4gdGhlIGFib3ZlIG91dHB1dCwgYnV0IGl0IGlzIGVhc2llciB0byBqdXN0IHB1bGwgdGhpcyByb3cgb3V0IHVzaW5nIHRoaXMgZnVuY3Rpb24uIFdlIGNhbiBzZWUgdGhhdCB0aGUgbWVhbiBgcm1zZWAgdmFsdWUgYWNyb3NzIHRoZSBjcm9zcyB2YWxpZGF0aW9uIHNldHMgd2FzIDEuNzEyLiBCZWZvcmUgdHVuaW5nIGl0IHdhcyAxLjcyNSAgd2l0aCBhIHNpbWlsYXIgYHN0ZF9lcnJgIHNvIHRoZSBwZXJmb3JtYW5jZSB3YXMgdmVyeSBzbGlnaHRseSBpbXByb3ZlZC4KCgojIyBGaW5hbCBtb2RlbCBwZXJmb3JtYW5jZSBldmFsdWF0aW9uCgpOb3cgdGhhdCB3ZSBoYXZlIGRlY2lkZWQgdGhhdCB3ZSBoYXZlIHJlYXNvbmFibGUgcGVyZm9ybWFuY2Ugd2l0aCBvdXIgdHJhaW5pbmcgZGF0YSwgd2UgY2FuIHN0b3AgYnVpbGRpbmcgb3VyIG1vZGVsIGFuZCBldmFsdWF0ZSBwZXJmb3JtYW5jZSB3aXRoIG91ciB0ZXN0aW5nIGRhdGEuIAoKSGVyZSwgd2Ugd2lsbCB1c2UgdGhlIHJhbmRvbSBmb3Jlc3QgbW9kZWwgdGhhdCB3ZSBidWlsdCB0byBwcmVkaWN0IHZhbHVlcyBmb3IgdGhlIG1vbml0b3JzIGluIHRoZSB0ZXN0aW5nIGRhdGEgYW5kIHdlIHdpbGwgdXNlIHRoZSB2YWx1ZXMgZm9yIGBtdHJ5YCBhbmQgYG1pbl9uYCB0aGF0IHdlIGp1c3QgZGV0ZXJtaW5lZCBiYXNlZCBvbiBvdXIgdHVuaW5nIGFuYWx5c2lzIHRvIGFjaGlldmUgdGhlIGJlc3QgcGVyZm9ybWFuY2UuCgpTbywgZmlyc3Qgd2UgbmVlZCB0byBzcGVjaWZ5IHRoZXNlIHZhbHVlcyBpbiBhIHdvcmtmbG93LiBXZSBjYW4gdXNlIHRoZSBgc2VsZWN0X2Jlc3QoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlIHRvIGdyYWIgdGhlIHZhbHVlcyB0aGF0IHdlcmUgZGV0ZXJtaW5lZCB0byBiZSBiZXN0IGZvciBgbXRyeWAgYW5kIGBtaW5fbmAuCgoKCmBgYHtyfQoKdHVuZWRfUkZfdmFsdWVzPC0gc2VsZWN0X2Jlc3QodHVuZV9SRl9yZXN1bHRzLCAicm1zZSIpCnR1bmVkX1JGX3ZhbHVlcwpgYGAKCk5vdyB3ZSBjYW4gZmluYWxpemUgdGhlIG1vZGVsL3dvcmtmbG93IHRoYXQgd2Ugd2UgdXNlZCBmb3IgdHVuaW5nIHdpdGggdGhlc2UgdmFsdWVzLgoKCmBgYHtyfQpSRl90dW5lZF93ZmxvdyA8LVJGX3R1bmVfd2Zsb3cgJT4lCiAgdHVuZTo6ZmluYWxpemVfd29ya2Zsb3codHVuZWRfUkZfdmFsdWVzKQpgYGAKCgpXaXRoIHRoZSBgd29ya2Zsb3dzYCBwYWNrYWdlLCB3ZSBjYW4gdXNlIHRoZSBzcGxpdHRpbmcgaW5mb3JtYXRpb24gZm9yIG91ciBvcmlnaW5hbCBkYXRhIGBwbV9zcGxpdGAgdG8gZml0IHRoZSBmaW5hbCBtb2RlbCBvbiB0aGUgZnVsbCB0cmFpbmluZyBzZXQgYW5kIGFsc28gb24gdGhlIHRlc3RpbmcgZGF0YSB1c2luZyB0aGUgYGxhc3RfZml0KClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZS4gTm8gcHJlLXByb2Nlc3Npbmcgc3RlcHMgYXJlIHJlcXVpcmVkLgoKVGhlIHJlc3VsdHMgd2lsbCBzaG93IHRoZSBwZXJmb3JtYW5jZSB1c2luZyB0aGUgdGVzdGluZyBkYXRhLgoKCmBgYHtyfQpvdmVyYWxsZml0IDwtdHVuZTo6bGFzdF9maXQoUkZfdHVuZWRfd2Zsb3csIHBtX3NwbGl0KQogIyBvcgpvdmVyYWxsZml0IDwtUkZfd2Zsb3cgJT4lCiAgdHVuZTo6bGFzdF9maXQocG1fc3BsaXQpCmBgYAoKVGhlIGBvdmVyYWxsZml0YCBvdXRwdXQgaGFzIGEgbG90IG9mIHJlYWxseSB1c2VmdWwgaW5mb3JtYXRpb24gYWJvdXQgdGhlIG1vZGVsLCB0aGUgdGVzdGluZyBhbmQgdHJhaW5pbmcgZGF0YSBzcGxpdCwgYW5kIHRoZSBwcmVkaWN0aW9ucyBmb3IgdGhlIHRlc3RpbmcgZGF0YS4KClRvIHNlZSB0aGUgcGVyZm9ybWFuY2Ugb24gdGhlIHRlc3QgZGF0YSB3ZSBjYW4gdXNlIHRoZSBgY29sbGVjdF9tZXRyaWNzKClgIGZ1bmN0aW9uIGxpa2Ugd2UgZGlkIGJlZm9yZS4KYGBge3J9CiAgY29sbGVjdF9tZXRyaWNzKG92ZXJhbGxmaXQpCiAKYGBgCgpBd2Vzb21lISBXZSBjYW4gc2VlIHRoYXQgb3VyIHJtc2Ugb2YgMS40NCBpcyBxdWl0ZSBzaW1pbGFyIHdpdGggb3VyIHRlc3RpbmcgZGF0YSBjcm9zcyB2YWxpZGF0aW9uIHNldHMuIFdlIGFjaGlldmVkIHF1aXRlIGdvb2QgcGVyZm9ybWFuY2UsIHdoaWNoIHN1Z2dlc3RzIHRoYXQgd2Ugd291bGQgY291bGQgcHJlZGljdCBvdGhlciBsb2NhdGlvbnMgd2l0aCBtb3JlIHNwYXJzZSBtb25pdG9yaW5nIGJhc2VkIG9uIG91ciBwcmVkaWN0b3JzIHdpdGggcmVhc29uYWJsZSBhY2N1cmFjeS4KCk5vdyBpZiB5b3Ugd2FudGVkIHRvIHRha2UgYSBsb29rIGF0IHRoZSBwcmVkaWN0ZWQgdmFsdWVzIGZvciB0aGUgdGVzdCBzZXQgKHRoZSAyOTIgcm93cyB3aXRoIHByZWRpY3Rpb25zIG91dCBvZiB0aGUgODc2IG9yaWdpbmFsIG1vbml0b3IgdmFsdWVzKSB5b3UgY2FuIHVzZSB0aGUgIGBjb2xsZWN0X3ByZWRpY3Rpb25zKClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZSgpYCBwYWNrYWdlOgoKYGBge3J9CnRlc3RfcHJlZGljdGlvbnMgPC1jb2xsZWN0X3ByZWRpY3Rpb25zKG92ZXJhbGxmaXQpCmBgYAoKYGBge3IsIGV2YWwgPSBGQUxTRX0KdGVzdF9wcmVkaWN0aW9ucwpgYGAKCiMjIyMgey5zY3JvbGxhYmxlIH0KYGBge3IsIGVjaG8gPUZBTFNFfQp0ZXN0X3ByZWRpY3Rpb25zICU+JQogIHByaW50KG4gPSAxZTMpCmBgYAoKIyMjIwoKTmljZSEKCiMgKipEYXRhIFZpc3VhbGl6YXRpb24qKgoqKioKCk91ciBtYWluIHF1ZXN0aW9uIGZvciB0aGlzIGNhc2Ugc3R1ZHkgd2FzOiAgCgo+IENhbiB3ZSBwcmVkaWN0IGFubnVhbCBhdmVyYWdlIGFpciBwb2xsdXRpb24gY29uY2VudHJhdGlvbnMgYXQgdGhlIGdyYW51bGFyaXR5IG9mIHppcCBjb2RlIHJlZ2lvbmFsIGxldmVscyB1c2luZyBwcmVkaWN0b3JzIHN1Y2ggYXMgZGF0YSBhYm91dCBwb3B1bGF0aW9uIGRlbnNpdHksIHVyYmFuaXphdGlvbiwgcm9hZCBkZW5zaXR5LCBhcyB3ZWxsIGFzLCBzYXRlbGxpdGUgcG9sbHV0aW9uIGRhdGEgYW5kIGNoZW1pY2FsIG1vZGVsaW5nIGRhdGE/CgpUaHVzIGZhciwgd2UgaGF2ZSBidWlsZCBhIG1hY2hpbmUgbGVhcm5pbmcgKE1MKSBtb2RlbCB0byBwcmVkaWN0IGZpbmUgcGFydGljdWxhdGUgbWF0dGVyIGFpciBwb2xsdXRpb24gbGV2ZWxzIGJhc2VkIG9uIG91ciBwcmVkaWN0b3IgdmFyaWFibGVzIChvciBmZWF0dXJlcykuCgpOb3csIGxldCdzIG1ha2UgYSBwbG90IG9mIG91ciBwcmVkaWN0ZWQgb3V0Y29tZSB2YWx1ZXMgKCRcaGF0e1l9JCkgYW5kIGFjdHVhbCBvdXRjb21lIHZhbHVlcyAkWSQgd2Ugb2JzZXJ2ZWQuIAoKRmlyc3QsIGxldCdzIHN0YXJ0IGJ5IG1ha2luZyBhIHBsb3Qgb2Ygb3VyIG1vbml0b3JzLiAKVG8gZG8gdGhpcywgd2Ugd2lsbCB1c2UgdGhlIGZvbGxvd2luZyBwYWNrYWdlcyB0byBjcmVhdGUgYSBtYXAgb2YgdGhlIFVTOgoKMS4gYHNmYCAtIHRoZSBzaW1wbGUgZmVhdHVyZXMgcGFja2FnZSBoZWxwcyB0byBjb252ZXJ0IGdlb2dyYXBoaWNhbCBjb29yZGluYXRlcyBpbnRvIGBnZW9tZXRyeWAgdmFyaWFibGVzIHdoaWNoIGFyZSB1c2VmdWwgZm9yIG1ha2luZyAyRCBwbG90cwoyLiBgbWFwc2AgLSB0aGlzIHBhY2thZ2UgY29udGFpbnMgZ2VvZ3JhcGhpY2FsIG91dGxpbmVzIGFuZCBwbG90dGluZyBmdW5jdGlvbnMgdG8gY3JlYXRlIHBsb3RzIHdpdGggbWFwcyAKMy4gYHJuYXR1cmFsZWFydGhgLSB0aGlzIGFsbG93cyBmb3IgZWFzeSBpbnRlcmFjdGlvbiB3aXRoIG1hcCBkYXRhIGZyb20gW05hdHVyYWwgRWFydGhdKGh0dHA6Ly93d3cubmF0dXJhbGVhcnRoZGF0YS5jb20vKSB3aGljaCBpcyBhIHB1YmxpYyBkb21haW4gbWFwIGRhdGFzZXQKNC4gYHJnZW9zYCAtIHRoaXMgcGFja2FnZSBpbnRlcmZhY2VzIHdpdGggdGhlIEdlb21ldHJ5IEVuZ2luZS1PcGVuIFNvdXJjZSAoYEdFT1NgKSB3aGljaCBpcyBhbHNvIGhlbHBmdWwgZm9yIGNvb3JkaW5hdGUgY29udmVyc2lvbgoKV2Ugd2lsbCBzdGFydCB3aXRoIGdldHRpbmcgYW4gb3V0bGluZSBvZiB0aGUgVVMgd2l0aCB0aGUgYG5lX2NvdW50cmllcygpYCBmdW5jdGlvbiBvZiB0aGUgYHJuYXR1cmFsZWFydGhgIHBhY2thZ2Ugd2hpY2ggd2lsbCByZXR1cm4gcG9seWdvbnMgb2YgdGhlIGNvdW50cmllcyBpbiB0aGUgW05hdHVyYWwgRWFydGhdKGh0dHA6Ly93d3cubmF0dXJhbGVhcnRoZGF0YS5jb20vKSBkYXRhc2V0LgoKYGBge3J9Cgp3b3JsZCA8LSBuZV9jb3VudHJpZXMoc2NhbGUgPSAibWVkaXVtIiwgcmV0dXJuY2xhc3MgPSAic2YiKQpnbGltcHNlKHdvcmxkKQoKYGBgCgoKSGVyZSB5b3UgY2FuIHNlZSB0aGUgZGF0YSBhYm91dCB0aGUgY291bnRyaWVzIGluIHRoZSB3b3JsZC4gTm90aWNlIHRoZSBgZ2VvbWV0cnlgIHZhcmlhYmxlLiBUaGlzIGlzIHVzZWQgdG8gY3JlYXRlIHRoZSBvdXRsaW5lcyB0aGF0IHdlIHdhbnQuIAoKTm93IHdlIGNhbiB1c2UgdGhlIGBnZW9tX3NmKClgIGZ1bmN0aW9uIG9mIHRoZSBgZ2dwbG90MmAgcGFja2FnZSB0byBjcmVhdGUgYSB2aXN1YWwgb2Ygc2ltcGxlIGZlYXR1cmUgKHRoZSBnZW9tZXRyeSBjb29yZGluYXRlcyBmb3VuZCBpbiB0aGUgYGdlb21ldHJ5YCB2YXJpYWJsZSkuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSB3b3JsZCkgKwogICAgZ2VvbV9zZigpIAoKYGBgCgpTbyBub3cgd2UgY2FuIHNlZSB0aGF0IHdlIGhhdmUgb3V0bGluZXMgb2YgYWxsIHRoZSBjb3VudHJpZXMgaW4gdGhlIHdvcmxkLgoKV2Ugd2FudCB0byBsaW1pdCB0aGlzIGp1c3QgdG8gdGhlIGNvb3JkaW5hdGVzIGZvciB0aGUgVVMuIFdlIHdpbGwgZG8gdGhpcyBiYXNlZCBvbiB0aGUgY29vcmRpbmF0ZXMgd2UgZm91bmQgb24gV2lraXBlZGlhLiBBY2NvcmRpbmcgdG8gdGhpcyBbbGlua10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGlzdF9vZl9leHRyZW1lX3BvaW50c19vZl90aGVfVW5pdGVkX1N0YXRlcyNXZXN0ZXJubW9zdCl7dGFyZ2V0PSJfYmxhbmsifSwgdGhlc2UgYXJlIHRoZSBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIGJvdW5kcyBvZiB0aGUgY29udGluZW50YWwgVVM6CgotIHRvcCA9IDQ5LjM0NTc4NjggIyBub3J0aCBsYXQKLSBsZWZ0ID0gLTEyNC43ODQ0MDc5ICMgd2VzdCBsb25nCi0gcmlnaHQgPSAtNjYuOTUxMzgxMiAjIGVhc3QgbG9uZwotIGJvdHRvbSA9ICAyNC43NDMzMTk1ICMgc291dGggbGF0CgpgYGB7cn0KCmdncGxvdChkYXRhID0gd29ybGQpICsKICAgIGdlb21fc2YoKSArCiAgICBjb29yZF9zZih4bGltID0gYygtMTI1LCAtNjYpLCB5bGltID0gYygyNC41LCA1MCksIAogICAgICAgICAgICAgZXhwYW5kID0gRkFMU0UpCmBgYApOb3cgd2UganVzdCBoYXZlIGEgcGxvdCB0aGF0IGlzIG1vc3RseSBsaW1pdGVkIHRvIHRoZSBvdXRsaW5lIG9mIHRoZSBVUy4KCk5vdyB3ZSB3aWxsIHVzZSB0aGUgYGdlb21fcG9pbnQoKWAgZnVuY3Rpb24gb2YgdGhlIGBnZ3Bsb3RgIHBhY2thZ2UgdG8gYWRkIHNjYXR0ZXIgcGxvdCBvbiB0b3Agb2YgdGhlIG1hcC4gV2Ugd2FudCB0byBzaG93IHdoZXJlIHRoZSBtb25pdG9ycyBhcmUgbG9jYXRlZCBiYXNlZCBvbiB0aGUgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSB2YWx1ZXMgaW4gdGhlIGRhdGEuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSB3b3JsZCkgKwogICAgZ2VvbV9zZigpICsKICAgIGNvb3JkX3NmKHhsaW0gPSBjKC0xMjUsIC02NiksIHlsaW0gPSBjKDI0LjUsIDUwKSwgCiAgICAgICAgICAgICBleHBhbmQgPSBGQUxTRSkrCiAgICBnZW9tX3BvaW50KGRhdGEgPSBwbSwgYWVzKHggPSBsb24sIHkgPSBsYXQpLCBzaXplID0gMiwgCiAgICAgICAgICAgICAgIHNoYXBlID0gMjMsIGZpbGwgPSAiZGFya3JlZCIpCgpgYGAKTmljZSEKCk5vdyBsZXQncyBhZGQgY291bnR5IGxpbmVzLgoKQ291bnR5IGdyYXBoaWNhbCBkYXRhIGlzIGF2YWlsYWJsZSBmcm9tIHRoZSBgbWFwc2AgcGFja2FnZS4gClRoZSBgc2ZgIHBhY2thZ2Ugd2hpY2ggYWdhaW4gaXMgc2hvcnQgZm9yIHNpbXBsZSBmZWF0dXJlcyBjcmVhdGVzIGEgZGF0YSBmcmFtZSBhYm91dCB0aGlzIGdyYXBoaWNhbCBkYXRhIHNvIHRoYXQgd2UgY2FuIHdvcmsgd2l0aCBpdC4KCmBgYHtyfQpjb3VudGllcyA8LSAKICBzZjo6c3RfYXNfc2YobWFwczo6bWFwKCJjb3VudHkiLCBwbG90ID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IFRSVUUpKQoKY291bnRpZXMKYGBgCgpOb3cgd2Ugd2lsbCB1c2UgdGhpcyBkYXRhIHdpdGhpbiB0aGUgYGdlb21fc2YoKWAgZnVuY3Rpb24gdG8gYWRkIHRoaXMgdG8gb3VyIHBsb3QuICBXZSB3aWxsIGFsc28gYWRkIGEgdGl0bGUgdXNpbmcgdGhlIGBnZ3RpdGxlKClgIGZ1bmN0aW9uLCBhcyB3ZWxsIGFzIHJlbW92ZSBheGlzIHRpY2tzIGFuZCB0aXRsZXMgdXNpbmcgdGhlIGB0aGVtZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGdncGxvdDJgIHBhY2thZ2UuCgpgYGB7cn0KbW9uaXRvcnMgPC0gZ2dwbG90KGRhdGEgPSB3b3JsZCkgKwogICAgZ2VvbV9zZihkYXRhID0gY291bnRpZXMsIGZpbGwgPSBOQSwgY29sb3IgPSBncmF5KC41KSkrCiAgICAgIGNvb3JkX3NmKHhsaW0gPSBjKC0xMjUsIC02NiksIHlsaW0gPSBjKDI0LjUsIDUwKSwgCiAgICAgICAgICAgICBleHBhbmQgPSBGQUxTRSkgKwogICAgZ2VvbV9wb2ludChkYXRhID0gcG0sIGFlcyh4ID0gbG9uLCB5ID0gbGF0KSwgc2l6ZSA9IDIsIAogICAgICAgICAgICAgICBzaGFwZSA9IDIzLCBmaWxsID0gImRhcmtyZWQiKSArCiAgICBnZ3RpdGxlKCJNb25pdG9yIExvY2F0aW9ucyIpICsKICAgIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkKCm1vbml0b3JzCmBgYAoKR3JlYXQhCgpOb3csIGxldCdzIGFkZCBhIGZpbGwgYXQgdGhlIGNvdW50eS1sZXZlbCBmb3IgdGhlIHRydWUgbW9uaXRvciB2YWx1ZXMgb2YgYWlyIHBvbGx1dGlvbi4KCkZpcnN0LCB3ZSBuZWVkIHRvIGdldCB0aGUgY291bnR5IG1hcCBkYXRhIHRoYXQgd2UganVzdCBnb3QgYW5kIG91ciBhaXIgcG9sbHV0aW9uIGRhdGEgdG8gaGF2ZSBzaW1pbGFybHkgZm9ybWF0dGVkIGNvdW50eSBuYW1lcyBzbyB0aGF0IHdlIGNhbiBjb21iaW5lIHRoZSBkYXRhc2V0cyB0b2dldGhlci4KCldlIGNhbiBzZWUgdGhhdCBpbiB0aGUgYGNvdW50eWAgZGF0YSB0aGUgY291bnRpZXMgYXJlIGxpc3RlZCBhZnRlciB0aGUgc3RhdGUgbmFtZSBhbmQgYSBjb21tYS4gSW4gYWRkaXRpb24gdGhleSBhcmUgYWxsIGxvd2VyIGNhc2UuCgoKYGBge3J9CmhlYWQoY291bnRpZXMpCmBgYAoKSW4gY29udHJhc3QsIG91ciBhaXIgcG9sbHV0aW9uIGBwbWAgZGF0YSBzaG93cyBjb3VudGllcyBhcyB0aXRsZXMgd2l0aCB0aGUgZmlyc3QgbGV0dGVyIGFzIHVwcGVyIGNhc2UuIAoKYGBge3J9CmRwbHlyOjpwdWxsKHBtLCBjb3VudHkpICU+JQogIGhlYWQoKQpgYGAKCldlIGNhbiB1c2UgdGhlIGBzZXBhcmF0ZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHRpZHlyYCBwYWNrYWdlIHRvIHNlcGFyYXRlIHRoZSBgSURgIHZhcmlhYmxlIG9mIG91ciBgY291bnRpZXNgIGRhdGEgaW50byB0d28gYHZhcmlhYmxlc2AgYmFzZWQgb24gdGhlIGNvbW1hIGFzIGEgc2VwYXJhdG9yLgoKYGBge3J9CmNvdW50aWVzICU8PiUgCiAgdGlkeXI6OnNlcGFyYXRlKElELCBpbnRvID0gYygic3RhdGUiLCAiY291bnR5IiksIHNlcCA9ICIsIikKCmhlYWQoY291bnRpZXMpCmBgYApOb3cgd2UganVzdCBuZWVkIHRvIG1ha2UgdGhlc2UgbmFtZXMgaW4gdGhlIG5ldyBgY291bnR5YCB2YXJpYWJsZSBvZiB0aGUgYGNvdW50aWVzYCBkYXRhIHRvIGJlIGluIHRpdGxlIGZvcm1hdC4gV2UgY2FuIHVzZSB0aGUgYHN0cl90b190aXRsZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHN0cmluZ3JgIHBhY2thZ2UgdG8gZG8gdGhpcy4gCmBgYHtyfQpjb3VudGllc1tbImNvdW50eSJdXSA8LSBzdHJpbmdyOjpzdHJfdG9fdGl0bGUoY291bnRpZXNbWyJjb3VudHkiXV0pCmBgYAoKR3JlYXQhIE5vdyB0aGUgY291bnR5IGluZm9ybWF0aW9uIGlzIHRoZSBzYW1lIGZvciB0aGUgYGNvdW50aWVzYCBhbmQgYHBtYCBkYXRhLgoKV2UgY2FuIHVzZSB0aGUgYGlubmVyX2pvaW4oKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSB0byBqb2luIHRoZSBkYXRhc2V0cyB0b2dldGhlciBiYXNlZCBvbiB0aGUgYGNvdW50eWAgdmFyaWFibGVzIGluIGVhY2guIFRoaXMgZnVuY3Rpb24gd2lsbCBrZWVwIGFsbCByb3dzIHRoYXQgYXJlIGluIGJvdGggZGF0YXNldHMuCgpgYGB7cn0KbWFwX2RhdGEgPC1kcGx5cjo6aW5uZXJfam9pbihjb3VudGllcywgcG0sIGJ5ID0gImNvdW50eSIpCgpnbGltcHNlKG1hcF9kYXRhKQoKYGBgCk5pY2UhIHdlIGNhbiBzZWUgdGhhdCB3ZSBoYXZlIGFkZCBhIGBnZW9tYCB2YXJpYWJsZSB0byB0aGUgYHBtYCBkYXRhLgoKTm93IHdlIGNhbiB1c2UgdGhpcyB0byBjb2xvciB0aGUgY291bnRpZXMgaW4gb3VyIHBsb3QgYmFzZWQgb24gdGhlIGB2YWx1ZWAgdmFyaWFibGUgb2Ygb3VyIGBwbWAgZGF0YSwgd2hpY2ggeW91IG1heSByZWNhbGwgaXMgdGhlIGFjdHVhbCBtb25pdG9yIGRhdGEgZm9yIGZpbmUgcGFydGljdWxhdGUgYWlyIHBvbGx1dGlvbiBhdCBlYWNoIG1vbml0b3IuIAoKV0UgY2FuIGRvIHNvIHVzaW5nIHRoZSBgc2NhbGVfZmlsbF9ncmFkaWVudG4oKWAgZnVuY3Rpb24gb2YgdGhlIGBnZ3Bsb3QyYCBwYWNrYWdlIHdoaWNoIGNyZWF0ZXMgY29sb3IgZ3JhZGllbnQgYmFzZWQgb24gYSB2YXJpYWJsZS4gSW4gdGhpcyBjYXNlIGl0IGlzIHRoZSB2YXJpYWJsZSB0aGF0IHdhcyBzcGVjaWZpZWQgYXMgdGhlIGBmaWxsYCBpbiB0aGUgYGFlc2AgZnVuY3Rpb24gb2YgdGhlIGBnZW9tX3NmKClgIGZ1bmN0aW9uLiBXZSBzcGVjaWZpZWQgdGhhdCBpdCB3b3VsZCBiZSB0aGUgYHZhbHVlYCB2YXJpYWJsZSBvZiB0aGUgYHBtYCBkYXRhLgoKVGhpcyBgc2NhbGVfZmlsbF9ncmFkaWVudG4oKWAgZnVuY3Rpb24gIGFsc28gYWxsb3dzIHlvdSB0byBzcGVjaWZ5IHRoZSBjb2xvcnMsIHdoYXQgdG8gZG8gYWJvdXQgTkEgdmFsdWVzIChzaG91bGQgdGhleSBiZSBhIHNwZWNpZmljIGNvbG9yIG9yIHRyYW5zcGFyZW50KSBhbmQgdGhlIGJyZWFrcywgbGltaXRzLCBsYWJlbHMgYW5kIG5hbWUvdGl0bGUgb24gdGhlIGxlZ2VuZCBmb3IgdGhlIGNvbG9yIGdyYWRpZW50LiAKCmBgYHtyfQoKdHJ1dGggPC1nZ3Bsb3QoZGF0YSA9IHdvcmxkKSArCiAgY29vcmRfc2YoeGxpbSA9IGMoLTEyNSwgLTY2KSwgeWxpbSA9IGMoMjQuNSwgNTApLCBleHBhbmQgPSBGQUxTRSkrCiAgICBnZW9tX3NmKGRhdGEgPSBtYXBfZGF0YSwgYWVzKGZpbGwgPSB2YWx1ZSkpICsKICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPXRvcG8uY29sb3JzKDcpLCBuYS52YWx1ZSA9ICJ0cmFuc3BhcmVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcz1jKDAsMTAsMjApLGxhYmVscz1jKDAsMTAsMjApLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW1pdHM9YygwLDIzLjUpLCBuYW1lID0gIlBNIHVnL20zIikgKwogIGdndGl0bGUoIlRydWUgUE0gMi41IGxldmVscyIpICsKICAgIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkKCnRydXRoCgpgYGAKTmljZSEKCk5vdyBsZXQncyBkbyB0aGUgc2FtZSB3aXRoIG91ciBwcmVkaWN0ZWQgb3V0Y29tZSB2YWx1ZXMuCgpMZXQncyBncmFiIGJvdGggdGhlIHRlc3RpbmcgYW5kIHRyYWluaW5nIHByZWRpY3RlZCBvdXRjb21lIHZhbHVlcyBzbyB0aGF0IHdlIGhhdmUgYXMgbXVjaCBkYXRhIGFzIHBvc3NpYmxlLiAKCkZpcnN0IHdlIG5lZWQgdG8gZml0IG91ciB0cmFpbmluZyBkYXRhIHdpdGggb3VyIGZpbmFsIG1vZGVsIHRvIGJlIGFibGUgdG8gZ2V0IHRoZSBwcmVkaWN0aW9ucyBmb3IgdGhlIG1vbml0b3JzIGluY2x1ZGVkIGluIHRoZSB0cmFpbmluZyBzZXQuIFdlIGRpZCB0aGlzIHVzaW5nIHRoZSBgbGFzdF9maXQoKWAgZnVuY3Rpb24sIGJ1dCB0aGUgb3V0cHV0IG9mIHRoaXMgbWFrZXMgaXQgZGlmZmljdWx0IHRvIGdyYWIgdGhlIHByZWRpY3RlZCB2YWx1ZXMgZm9yIHRoZSB0cmFpbmluZyBkYXRhLCBhbmQgaXQgaXMgYWxzbyBkaWZmaWN1bHQgdG8gZ2V0IHRoZSBpZCB2YXJpYWJsZXMgZm9yIHRoZSB0ZXN0aW5nIGRhdGEuIAoKClRodXMgd2Ugd2lsbCB1c2UgdGhlIHBhcnNuaXAgYGZpdCgpYCBhbmQgYHByZWRpY3QoKWAgZnVuY3Rpb25zIG9mIHRoZSBgcGFyc25pcGAgcGFja2FnZSB0byBkbyB0aGlzIGxpa2Ugc286CgojIyMjIHsudGhpbmtfcXVlc3Rpb25fYmxvY2t9CjxiPjx1PiBRdWVzdGlvbiBPcHBvcnR1bml0eSA8L3U+PC9iPgoKV2h5IGRvIHdlIG5vdCBuZWVkIHByZS1wcm9jZXNzZWQgZGF0YT8KCiMjIyMKCioqKgoKPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHJldmVhbCB0aGUgYW5zd2VyLiA8L3N1bW1hcnk+CgpTaW5jZSB3ZSBhcmUgdXNpbmcgYSB3b3JrZmxvdywgdGhlIGRhdGEgd2lsbCBiZSBwcmUtcHJvY2Vzc2VkIHdoZW4gaXQgaXMgZml0IGFzIHdlbGwuCgo8L2RldGFpbHM+CioqKgoKCmBgYHtyfQoKUkZfZmluYWxfdHJhaW5fZml0IDwtIHBhcnNuaXA6OmZpdChSRl90dW5lZF93ZmxvdywgZGF0YSA9IHRyYWluX3BtKQpSRl9maW5hbF90ZXN0X2ZpdCA8LSBwYXJzbmlwOjpmaXQoUkZfdHVuZWRfd2Zsb3csIGRhdGEgPSB0ZXN0X3BtKQoKCnZhbHVlc19wcmVkX3RyYWluIDwtIAogIHByZWRpY3QoUkZfZmluYWxfdHJhaW5fZml0LCB0cmFpbl9wbSkgJT4lIAogIGJpbmRfY29scyh0cmFpbl9wbSAlPiUgc2VsZWN0KHZhbHVlLCBmaXBzLCBjb3VudHksIGlkKSkgCgp2YWx1ZXNfcHJlZF90cmFpbgoKdmFsdWVzX3ByZWRfdGVzdCA8LSAKICBwcmVkaWN0KFJGX2ZpbmFsX3Rlc3RfZml0LCB0ZXN0X3BtKSAlPiUgCiAgYmluZF9jb2xzKHRlc3RfcG0gJT4lIHNlbGVjdCh2YWx1ZSwgZmlwcywgY291bnR5LCBpZCkpIAoKdmFsdWVzX3ByZWRfdGVzdApgYGAKCk5vdyB3ZSBjYW4gY29tYmluZSB0aGlzIGRhdGEgZm9yIHRoZSBwcmVkaWN0aW9ucyBmb3IgYWxsIG1vbml0b3JzIHVzaW5nIHRoZSBgYmluZF9yb3dzKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UsIHdoaWNoIHdpbGwgZXNzZW50aWFsbHkgYXBwZW5kIHRoZSBzZWNvbmQgZGF0YXNldCB0byB0aGUgZmlyc3QuCgpgYGB7cn0KYWxsX3ByZWQgPC0gYmluZF9yb3dzKHZhbHVlc19wcmVkX3Rlc3QsIHZhbHVlc19wcmVkX3RyYWluKQoKYWxsX3ByZWQKYGBgCgpHcmVhdCEgYXMgd2UgY2FuIHNlZSB0aGVyZSBhcmUgODc2IHZhbHVlcyBsaWtlIHdlIHdvdWxkIGV4cGVjdCBmb3IgYWxsIG9mIHRoZSBtb25pdG9ycy4gV2UgY2FuIHVzZSB0aGUgYGNvdW50eWAgdmFyaWFibGUgdG8gY29tYmluZSB0aGlzIHdpdGggdGhlIGBjb3VudGllc2AgZGF0YSBsaWtlIHdlIGRpZCB3aXRoIHRoZSBgcG1gIGRhdGEgcHJldmlvdXNseSBzbyB0aGF0IHdlIGNhbiB1c2UgdGhlIGB2YWx1ZWAgdmFyaWFibGUgYXMgYSBjb2xvciBzY2hlbWUgZm9yIG91ciBtYXAuCgoKYGBge3J9Cm1hcF9kYXRhIDwtIGlubmVyX2pvaW4oY291bnRpZXMsIGFsbF9wcmVkLCBieSA9ICJjb3VudHkiKQoKcHJlZCA8LSBnZ3Bsb3QoZGF0YSA9IHdvcmxkKSArCiAgICAgICAgICBjb29yZF9zZih4bGltID0gYygtMTI1LCAtNjYpLCB5bGltID0gYygyNC41LCA1MCksIAogICAgICAgICAgICAgICAgIGV4cGFuZCA9IEZBTFNFKSArCiAgICBnZW9tX3NmKGRhdGEgPSBtYXBfZGF0YSwgYWVzKGZpbGwgPSAucHJlZCkpICsKICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzPXRvcG8uY29sb3JzKDcpLCBuYS52YWx1ZSA9ICJ0cmFuc3BhcmVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzPWMoMCwxMCwyMCksbGFiZWxzPWMoMCwxMCwyMCksCiAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoMCwyMy41KSwgbmFtZSA9ICJQTSB1Zy9tMyIpICsKICBnZ3RpdGxlKCJQcmVkaWN0ZWQgUE0gMi41IGxldmVscyIpKwogICAgdGhlbWUoYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKQoKcHJlZApgYGAKCk5vdyB3ZSB3aWxsIHVzZSB0aGUgYHBhdGNod29ya2AgcGFja2FnZSB0byBjb21iaW5lIG91ciBsYXN0IHR3byBwbG90cy4gVGhpcyBhbGxvd3MgdXMgdG8gY29tYmluZSBwbG90cyB1c2luZyB0aGUgYCtgIG9yIHRoZSBgL2AgLiBUaGUgYCtgIHdpbGwgcGxhY2UgcGxvdHMgc2lkZSBieSBzaWRlIGFuZCB0aGUgYC9gIHdpbGwgcGxhY2UgcGxvdHMgdG9wIHRvIGJvdHRvbS4KCgpOb3cgbGV0J3MganVzdCBjb21iaW5lIHRoZSB0cnV0aCBwbG90IGFuZCB0aGUgcHJlZGljdGlvbiBwbG90cyB0b2dldGhlcjoKYGBge3J9CnRydXRoL3ByZWQKCmBgYAoKV2UgY2FuIHNlZSB0aGF0IHRoZSBwcmVkaWN0ZWQgZmluZSBwYXJ0aWNsZSBhaXIgcG9sbHV0aW9uIHZhbHVlcyBpbiAodWcvbTMpIGFyZSBxdWl0ZSBzaW1pbGFyIHRvIHRoZSB0cnVlIHZhbHVlcyBtZWFzdXJlZCBieSB0aGUgYWN0dWFsIGdyYXZpbWV0cmljIG1vbml0b3JzLiBXZSBjYW4gYWxzbyBzZWUgdGhhdCBzb3V0aGVybiBDYWxpZm9ybmlhIGhhcyBzb21lIGxhcmdlIGNvdW50aWVzIHdpdGggd29yc2UgcG9sbHV0aW9uIChhcyB0aGV5IGFyZSB5ZWxsb3cgYW5kIHRodXMgaGF2ZSBtdWNoIGhpZ2hlciBwYXJ0aWN1bGF0ZSBtYXR0ZXIgbGV2ZWxzKS4KCkxldCdzIGFkZCBzb21lIHRleHQgdG8gb3VyIHBsb3QgdG8gZXhwbGFpbiBpdCBhIGJpdCBtb3JlLiBXZSBjYW4gZG8gc28gdXNpbmcgdGhlIGBwbG90X2Fubm90YXRpb24oKWAgZnVuY3Rpb24gb2YgdGhlIGBwYXRjaHdvcmtgIHBhY2thZ2UuIFRoZSBgdGhlbWVgIGFyZ3VtZW50IG9mIHRoaXMgZnVuY3Rpb24gdGFrZXMgdGhlIHNhbWUgdGhlbWUgaW5mb3JtYXRpb24gdXNpbmcgdGhlIGB0aGVtZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGdncGxvdDJgIHBhY2thZ2UgYXMgd2hlbiBjcmVhdGluZyBgZ2dwbG90MmBwbG90cy4KCmBgYHtyfQoodHJ1dGgvcHJlZCkgKyBwbG90X2Fubm90YXRpb24odGl0bGUgPSAiTWFjaGluZSBMZWFybmluZyBNZXRob2RzIEFsbG93IGZvciBQcmVkaWN0aW9uIG9mIEFpciBQb2xsdXRpb24iLCBzdWJ0aXRsZSA9ICJBIHJhbmRvbSBmb3Jlc3QgbW9kZWwgcHJlZGljdHMgdHJ1ZSBtb25pdG9yZWQgbGV2ZWxzIG9mIGZpbmUgcGFydGljdWxhdGUgbWF0dGVyIChQTSAyLjUpIGFpciBwb2xsdXRpb24gYmFzZWQgb25cbmRhdGEgYWJvdXQgcG9wdWxhdGlvbiBkZW5zaXR5IGFuZCBvdGhlciBwcmVkaWN0b3JzIHJlYXNvbmFibHkgd2VsbCwgdGh1cyBzdWdnZXN0aW5nIHRoYXQgd2UgY2FuIHByZWRpY3QgbGV2ZWxzXG5vZiBwb2xsdXRpb24gaW4gcGxhY2VzIHdpdGggcG9vciBtb25pdG9yaW5nIiwgdGhlbWUgPSB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPTEyLCBmYWNlID0gImJvbGQiKSwgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpKQoKYGBgCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXZhbD1GQUxTRX0KcG5nKGhlcmU6OmhlcmUoImltZyIsICJtYWluX3Bsb3RfbWFwcy5wbmciKSwgCiAgICBoZWlnaHQgPSAxNTAwLCB3aWR0aCA9IDIwMDAsIHJlcyA9IDMwMCkKKHRydXRoL3ByZWQpICsgcGxvdF9hbm5vdGF0aW9uKHRpdGxlID0gIk1hY2hpbmUgTGVhcm5pbmcgTWV0aG9kcyBBbGxvdyBmb3IgUHJlZGljdGlvbiBvZiBBaXIgUG9sbHV0aW9uIiwgc3VidGl0bGUgPSAiQSByYW5kb20gZm9yZXN0IG1vZGVsIHByZWRpY3RzIHRydWUgbW9uaXRvcmVkIGxldmVscyBvZiBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlciAoUE0gMi41KSBhaXIgcG9sbHV0aW9uIGJhc2VkIG9uXG5kYXRhIGFib3V0IHBvcHVsYXRpb24gZGVuc2l0eSBhbmQgb3RoZXIgcHJlZGljdG9ycyByZWFzb25hYmx5IHdlbGwsIHRodXMgc3VnZ2VzdGluZyB0aGF0IHdlIGNhbiBwcmVkaWN0IGxldmVsc1xub2YgcG9sbHV0aW9uIGluIHBsYWNlcyB3aXRoIHBvb3IgbW9uaXRvcmluZyIsIHRoZW1lID0gdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0xMiwgZmFjZSA9ICJib2xkIiksIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSkKZGV2Lm9mZigpCmBgYAoKIyAqKlN1bW1hcnkqKgoqKioKCiMjIFN5bm9wc2lzCgpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIGV4cGxvcmVkIGdyYXZpbWV0cmljIG1vbml0b3JpbmcgZGF0YSBvZiBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlciBhaXIgcG9sbHV0aW9uIChvdXRjb21lIHZhcmlhYmxlKS4gCk91ciBnb2FsIHdhcyB0byBhYmxlIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbiB3aGVyZSB3ZSBvbmx5IGhhZCBwcmVkaWN0b3IgdmFyaWFibGVzIChvciBmZWF0dXJlcykgd2l0aG91dCBoYXZpbmcgb2JzZXJ2ZWQgYSBjb3JyZXNwb25kaW5nIG1lYXN1cmVtZW50IG9mIGFpciBwb2xsdXRpb24uCgpPdXIgbGVhcm5pbmcgb2JqZWN0aXZlcyB3ZXJlOiAKCi0gSW50cm9kdWNlIGNvbmNlcHRzIGluIG1hY2hpbmUgbGVhcm5pbmcKLSBEZW1vbnN0cmF0ZSBob3cgdG8gYnVpbGQgYSBtYWNoaW5lIGxlYXJuaW5nIG1vZGVsIHdpdGggYHRpZHltb2RlbHNgCi0gRGVtb25zdHJhdGUgaG93IHRvIHZpc3VhbGl6ZSBnZW8tc3BhdGlhbCBkYXRhIHVzaW5nIGBnZ3Bsb3QyYAoKVXNpbmcgdGhlIG1hY2hpbmUgbGVhcm5pbmcgbW9kZWxzIGJ1aWx0IGluIHRoaXMgY2FzZSBzdHVkeSwgd2UgY291bGQgbm93IGV4dGVuZCB0aGlzIG1vZGVsIHRvIGJlIHVzZWQgdG8gcHJlZGljdCBhaXIgcG9sbHV0aW9uIGxldmVscyBpbiBhcmVhcyB3aXRoIHBvb3IgbW9uaXRvcmluZywgdG8gaGVscCBpZGVudGlmeSByZWdpb25zIHdoZXJlIHBvcHVsYXRpb25zIG1heWJlIGVzcGVjaWFsbHkgYXQgcmlzayBmb3IgdGhlIGhlYWx0aCBlZmZlY3RzIG9mIGFpciBwb2xsdXRpb24uICAKCkFuYWx5c2VzIGxpa2UgdGhlIG9uZSBpbiBvdXIgY2FzZSBzdHVkeSBhcmUgaW1wb3J0YW50IGZvciBkZWZpbmluZyB3aGljaCBncm91cHMgY291bGQgYmVuZWZpdCB0aGUgbW9zdCBmcm9tIGludGVydmVudGlvbnMsIGVkdWNhdGlvbiwgYW5kIHBvbGljeSBjaGFuZ2VzIHdoZW4gYXR0ZW1wdGluZyB0byBtaXRpZ2F0ZSBwdWJsaWMgaGVhbHRoIGNoYWxsZW5nZXMuIFlvdSBjYW4gc2VlIGluIHRoaXMgW2FydGljbGVdKGh0dHBzOi8vd3d3Lm5lam0ub3JnL2RvaS9mdWxsLzEwLjEwNTYvTkVKTW9hMTcwMjc0Nyl7dGFyZ2V0PSJfYmxhbmsifSB0aGF0IG1hbnkgYWRkaXRpb25hbCBjb25zaWRlcmF0aW9ucyB3b3VsZCBiZSBpbnZvbHZlZCB0byBhZGVxdWF0ZWx5IHVuZGVyc3RhbmQgdGhlIGRhdGEgZW5vdWdoIHRvIHJlY29tbWVuZCBwb2xpY3kgY2hhbmdlcy4KCkhlcmUgYXJlIHNvbWUgdmlzdWFsIHN1bW1hcmllcyBhYm91dCB3aGF0IHdlIGxlYXJuZWQgYWJvdXQgdXNpbmcgYHRpZHltb2RlbHNgIHRvIHBlcmZvcm0gcHJlZGljdGlvbiBhbmFseXNlcy4KCkZpcnN0IHRoZSBtaW5pbWFsIHN0ZXBzIHJlcXVpcmVkOgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJ0aWR5bW9kZWxzQmFzaWNzLnBuZyIpKQpgYGAKCgpIZXJlIGlzIGEgZ3VpZGUgZm9yIG1vcmUgYWR2YW5jZWQgYW5hbHlzZXMgaW52b2x2aW5nIHByZXByb2Nlc3NpbmcsIGNyb3NzIHZhbGlkYXRpb24sIG9yIHR1bmluZzoKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiZnVsbF90aWR5bW9kZWxzX292ZXJ2aWV3LnBuZyIpKQpgYGAKCgoKCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayBoZXJlIGZvciBtb3JlIG9uIHdoYXQgd2UgbGVhcm5lZCB3aXRoIGB0aWR5bW9kZWxzYCA8L3N1bW1hcnk+CgpIZXJlLCB3ZSBwcm92aWRlIGFuIG92ZXJ2aWV3IG9mIHRoZSBgdGlkeW1vZGVsc2AgZnJhbWV3b3JrLiAKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwiZWNvc3lzdGVtLnBuZyIpKQpgYGAKCgpXZSBwZXJmb3JtZWQgdGhlIG1ham9yIHN0ZXBzIG9mIG1hY2hpbmUgbGVhcm5pbmcgdGhhdCB3ZSBpbnRyb2R1Y2VkIGluIHRoZSBiZWdpbm5pbmcgb2YgdGhlIGRhdGEgYW5hbHlzaXM6ICAKCjEuIERhdGEgZXhwbG9yYXRpb24gIAoKV2UgdXNlZCBwYWNrYWdlcyBsaWtlIGBza2ltcmAsIGBzdW1tYXJ5dG9vbHNgLCBgY29ycnBsb3RgLCBhbmQgYEdHYWxseWAgdG8gYmV0dGVyIHVuZGVyc3RhbmQgb3VyIGRhdGEuIFRoZXNlIHBhY2thZ2VzIGNhbiB0ZWxsIHVzIGhvdyBtYW55IG1pc3NpbmcgdmFsdWVzIGVhY2ggdmFyaWFibGUgaGFzIChpZiBhbnkpLCB0aGUgY2xhc3Mgb2YgZWFjaCB2YXJpYWJsZSwgdGhlIGRpc3RyaWJ1dGlvbiBvZiB2YWx1ZXMgZm9yIGVhY2ggdmFyaWFibGUsIHRoZSBzcGFyc2l0eSBvZiBlYWNoIHZhcmlhYmxlLCBhbmQgdGhlIGxldmVsIG9mIGNvcnJlbGF0aW9uIGJldHdlZW4gdmFyaWFibGVzLiAgCgoyLiBEYXRhIHNwbGl0dGluZyAKCldlIHVzZWQgdGhlIGByc2FtcGxlYCBwYWNrYWdlIHRvIGZpcnN0IHBlcmZvcm0gYW4gaW5pdGlhbCBzcGxpdCBvZiBvdXIgZGF0YSBpbnRvIHR3byBwaWVjZXM6IGEgdHJhaW5pbmcgc2V0IGFuZCBhIHRlc3Rpbmcgc2V0LiBUaGUgdHJhaW5pbmcgc2V0IHdhcyB1c2VkIHRvIG9wdGltaXplIHRoZSBtb2RlbCwgd2hpbGUgdGhlIHRlc3Rpbmcgc2V0IHdhcyB1c2VkIG9ubHkgdG8gZXZhbHVhdGUgdGhlIHBlcmZvcm1hbmNlIG9mIG91ciBmaW5hbCBtb2RlbC4gV2UgYWxzbyB1c2VkIHRoZSBgcnNhbXBsZWAgcGFja2FnZSB0byBjcmVhdGUgY3Jvc3MgdmFsaWRhdGlvbiBzdWJzZXRzIG9mIG91ciB0cmFpbmluZyBkYXRhLiBUaGlzIGFsbG93ZWQgdXMgdG8gYmV0dGVyIGFzc2VzcyB0aGUgcGVyZm9ybWFuY2Ugb2Ygb3VyIHRlc3RlZCBtb2RlbHMgdXNpbmcgb3VyIHRyYWluaW5nIGRhdGEuICAKCjMuIFZhcmlhYmxlIGFzc2lnbm1lbnQgYW5kIHByZS1wcm9jZXNzaW5nICAgCgpXZSB1c2VkIHRoZSBgcmVjaXBlc2AgcGFja2FnZSB0byBhc3NpZ24gdmFyaWFibGUgcm9sZXMgKHN1Y2ggYXMgb3V0Y29tZSwgcHJlZGljdG9yLCBhbmQgaWQgdmFyaWFibGUpLiBXZSBhbHNvIHVzZWQgdGhpcyBwYWNrYWdlIHRvIGNyZWF0ZSBhIHJlY2lwZSBmb3IgcHJlLXByb2Nlc3Npbmcgb3VyIHRyYWluaW5nIGFuZCB0ZXN0aW5nIGRhdGEuIFRoaXMgaW52b2x2ZWQgc3RlcHMgc3VjaCBhczogYCBzdGVwX2R1bW15YCB0byBjcmVhdGUgZHVtbXkgbnVtZXJpYyBlbmNvZGluZ3Mgb2Ygb3VyIGNhdGVnb3JpY2FsIHZhcmlhYmxlcywgYHN0ZXBfY29ycmAgdG8gcmVtb3ZlIGhpZ2hseSBjb3JyZWxhdGVkIHZhcmlhYmxlcywgYHN0ZXBfbnp2YCB0byByZW1vdmUgbmVhciB6ZXJvIHZhcmlhbmNlIHZhcmlhYmxlcyB0aGF0IHdvdWxkIGNvbnRyaWJ1dGUgbGl0dGxlIHRvIG91ciBtb2RlbCBhbmQgcG90ZW50aWFsbHkgYWRkIG5vaXNlLiAgV2UgbGVhcm5lZCB0aGF0IG9uY2Ugb3VyIHJlY2lwZSB3YXMgY3JlYXRlZCBhbmQgcHJlcHBlZCB1c2luZyBgcHJlcCgpYHdlIGNvdWxkIGV4dHJhY3QgdGhlIHByZS1wcm9jZXNzZWQgdHJhaW5pbmcgZGF0YSBvciBvdXIgcHJlLXByb2Nlc3NlZCB0ZXN0aW5nIGRhdGEgdXNpbmcgYGJha2UoKWAuIFdlIGFsc28gbGVhcm5lZCB0aGF0IGlmIHdlIHVzZWQgdGhlIG5ld2VyIHdvcmtmbG93cyBwYWNrYWdlIHRoYXQgd2UgZGlkIG5vdCBuZWVkIHRvIHVzZSB0aGUgYHByZXAoKWAgb3IgYGJha2UoKWAgZnVuY3Rpb25zLCBidXQgdGhhdCBpdCBpcyBzdGlsbCB1c2VmdWwgdG8ga25vdyBob3cgdG8gZG8gc28gaWYgd2Ugd2FudCB0byBsb29rIGF0IG91ciBkYXRhIGFuZCBob3cgdGhlIHJlY2lwZSBpcyBpbmZsdWVuY2luZyBpdCBtb3JlIGRlZXBseS4gIAoKNC4gTW9kZWwgc3BlY2lmaWNhdGlvbiwgZml0dGluZywgdHVuaW5nIGFuZCBwZXJmb3JtYW5jZSBldmFsdWF0aW9uIHVzaW5nIHRoZSB0cmFpbmluZyBkYXRhICAKCldlIGxlYXJuZWQgdGhhdCB0aGUgbW9kZWwgbmVlZHMgdG8gZmlyc3QgYmUgZml0IHRvIHRoZSB0cmFpbmluZyBkYXRhLiBXZSBsZWFybmVkIHRoYXQgaW4gYm90aCBjbGFzc2lmaWNhdGlvbiBhbmQgcHJlZGljdGlvbiwgdGhlIG1vZGVsIGlzIGZpdCB0byB0aGUgdHJhaW5pbmcgZGF0YSBhbmQgdGhlIGV4cGxhbmF0b3J5IHZhcmlhYmxlcyBhcmUgdXNlZCB0byBlc3RpbWF0ZSBudW1lcmljIHZhbHVlcyAoaW4gdGhlIGNhc2Ugb2YgcHJlZGljdGlvbikgb3IgY2F0ZWdvcmljYWwgdmFsdWVzIChpbiB0aGUgY2FzZSBvZiBjbGFzc2lmaWNhdGlvbikgb2YgdGhlIG91dGNvbWUgdmFyaWFibGUgb2YgaW50ZXJlc3QuIFdlIGxlYXJuZWQgdGhhdCB3ZSBzcGVjaWZ5IHRoZSBtb2RlbCBhbmQgaXRzIHNwZWNpZmljYXRpb25zIHVzaW5nIHRoZSBgcGFybnNpcGAgcGFja2FnZSBhbmQgdGhhdCB3ZSBhbHNvIHVzZSB0aGlzIHBhY2thZ2UgdG8gZml0IHRoZSBtb2RlbCB1c2luZyB0aGUgYGZpdCgpYCBmdW5jdGlvbi4gV2UgbGVhcm5lZCB0aGF0IGlmIHdlIGp1c3QgdXNlIGBwYXJzbmlwYCB0byBmaXQgdGhlIG1vZGVsLCB0aGVuIHdlIG5lZWQgdG8gdXNlIHRoZSBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgKG91dHB1dCBmcm9tIGBiYWtlKClgKS4gV2UgbGVhcm5lZCB0aGF0IHdlIGNhbiB1c2UgdGhlIHJhdyB0cmFpbmluZyBkYXRhIGlmIHdlIHVzZSB0aGUgYHdvcmtmbG93c2AgcGFja2FnZSB0byBjcmVhdGUgYSB3b3JrZmxvdyB0aGF0IHByZS1wcm9jZXNzZXMgb3VyIGRhdGEgZm9yIHVzLiAgIAoKV2UgbGVhcm5lZCB0aGF0IGlmIHRoZSBtb2RlbCBmaXRzIHdlbGwgdGhhbiB0aGUgZXN0aW1hdGVkIHZhbHVlcyB3aWxsIGJlIHZlcnkgc2ltaWxhciB0byB0aGUgdHJ1ZSBvdXRjb21lIHZhcmlhYmxlIHZhbHVlcyBpbiBvdXIgdHJhaW5pbmcgZGF0YS4gV2UgbGVhcm5lZCB0aGF0IHdlIGNhbiBhc3Nlc3MgbW9kZWwgcGVyZm9ybWFuY2UgdXNpbmcgdGhlIGB5YXJkc3RpY2tgIHBhY2thZ2Ugd2l0aCB0aGUgYG1ldHJpY3NgIGZ1bmN0aW8gb3IgdGhlIGB0dW5lYCBwYWNrYWdlIGFuZCB0aGUgYGNvbGxlY3RfbWV0cmljcygpYCBmdW5jdGlvbiAocmVxdWlyZWQgaWYgdXNpbmcgY3Jvc3MgdmFsaWRhdGlvbiBvciB0dW5pbmcpLiBXZSBhbHNvIGxlYXJuZWQgdGhhdCB3ZSBjYW4gdXNlIHN1YnNldHMgb2Ygb3VyIHRyYWluaW5nIGRhdGEgKHdoaWNoIHdlIGNyZWF0ZWQgd2l0aCB0aGUgYHJzYW1wbGVgIHBhY2thZ2UpIHRvIHBlcmZvcm0gY3Jvc3MgdmFsaWRhdGlvbiB0byBnZXQgYSBiZXR0ZXIgZXN0aW1hdGUgYWJvdXQgdGhlIHBlcmZvcm1hbmNlIG9mIG91ciBtb2RlbCB1c2luZyBvdXIgdHJhaW5pbmcgZGF0YSwgYXMgd2Ugd2FudCBvdXIgcmVzdWx0cyB0byBiZSBnZW5lcmFsaXphYmxlIGFuZCB0byBwZXJmb3JtIHdlbGwgd2l0aCBvdGhlciBkYXRhLCBub3QganVzdCBvdXIgdHJhaW5pbmcgZGF0YS4gV2UgdXNlZCB0aGUgYGZpdF9yZXNhbXBsZXMoKWAgZnVuY3Rpb24gb2YgdGhlIHR1bmUgcGFja2FnZSB0byBmaXQgb3VyIG1vZGVsIG9uIG91ciBkaWZmZXJlbnQgdHJhaW5pbmcgZGF0YSBzdWJzZXRzIGFuZCB0aGUgYGNvbGxlY3RfbWV0cmljcygpYCBmdW5jdGlvbiAoYWxzbyBvZiB0aGUgYHR1bmVgIHBhY2thZ2UpIHRvIGV2YWx1YXRlIG1vZGVsIHBlcmZvcm1hbmNlIHVzaW5nIHRoZXNlIHN1YnNldHMuICBXZSBhbHNvIGxlYXJuZWQgdGhhdCB3ZSBjYW4gcG90ZW50aWFsbHkgaW1wcm92ZSBtb2RlbCBwZXJmb3JtYW5jZSBieSB0dW5pbmcgYXNwZWN0cyBhYm91dCB0aGUgbW9kZWwgY2FsbGVkIFtoeXBlcnBhcmFtZXRlcnNdKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vZGlmZmVyZW5jZS1iZXR3ZWVuLWEtcGFyYW1ldGVyLWFuZC1hLWh5cGVycGFyYW1ldGVyLyl7dGFyZ2V0PSJfYmxhbmsifSB0byBkZXRlcm1pbmUgdGhlIGJlc3Qgb3B0aW9uIGZvciBtb2RlbCBwZXJmb3JtYW5jZS4gV2UgbGVhcm5lZCB0aGF0IHdlIGNhbiBkbyB0aGlzIHVzaW5nIHRoZSBgdHVuZWAgYW5kIGBkaWFsc2AgcGFja2FnZXMgYW5kIGV2YWx1YXRpbmcgdGhlIHBlcmZvcm1hbmNlIG9mIG91ciBtb2RlbCB3aXRoIHRoZSBkaWZmZXJlbnQgaHlwZXJwYXJhbWV0ZXIgb3B0aW9ucyBhbmQgb3VyIHRyYWluaW5nIGRhdGEgc3Vic2V0cyB0aGF0IHdlIHVzZWQgZm9yIGNyb3NzIHZhbGlkYXRpb24uIEFmdGVyIHdlIHRlc3RlZCBzZXZlcmFsIGRpZmZlcmVudCBtZXRob2RzIHRvIG1vZGVsIG91ciBkYXRhLCB3ZSBjb21wYXJlZCB0aGVtIHRvIGNob29zZSB0aGUgYmVzdCBwZXJmb3JtaW5nIG1vZGVsIGFzIG91ciBmaW5hbCBtb2RlbC4gIAoKCjUuIE92ZXJhbGwgbW9kZWwgcGVyZm9ybWFuY2UgZXZhbHVhdGlvbiAgCgpPbmNlIHdlIGNob3NlIG91ciBmaW5hbCBtb2RlbCwgd2UgZXZhbHVhdGVkIHRoZSBmaW5hbCBtb2RlbCBwZXJmb3JtYW5jZSB1c2luZyB0aGUgdGVzdGluZyBkYXRhIHVzaW5nIHRoZSBgbGFzdF9maXQoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlLiBUaGlzIGdpdmVzIHVzIGEgYmV0dGVyIGVzdGltYXRlIGFib3V0IGhvdyB3ZWxsIHRoZSBtb2RlbCB3aWxsIHByZWRpY3Qgb3IgY2xhc3NpZnkgdGhlIG91dGNvbWUgdmFyaWFibGUgb2YgaW50ZXJlc3Qgd2l0aCBuZXcgaW5kZXBlbmRlbnQgZGF0YS4gSWRlYWxseSBvbmUgd291bGQgYWxzbyBwZXJmb3JtIGFuIGV2YWx1YXRpb24gd2l0aCBpbmRlcGVuZGVudCBkYXRhIHRvIHByb3ZpZGUgYSBzZW5zZSBvZiBob3cgZ2VuZXJhbGl6YWJsZSB0aGUgbW9kZWwgaXMgdG8gb3RoZXIgZGF0YSBzb3VyY2VzLiAKCldlIGFsc28gc2F3IHRoYXQgd2UgY2FuIHVzZSB0aGUgYGNvbGxlY3RfcHJlZGljdGlvbnMoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlIHRvIGdldCB0aGUgcHJlZGljdGlvbnMgZm9yIG91ciB0ZXN0IGRhdGEuIFdlIHNhdyB0aGF0IHdlIGNhbiBnZXQgbW9yZSBkZXRhaWxlZCBwcmVkaWN0aW9uIGRhdGEgdXNpbmcgdGhlIGBwcmVkaWN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgcGFyc25pcGAgcGFja2FnZS4KCjwvZGV0YWlscz4KCgoKIyMgU3VnZ2VzdGVkIEhvbWV3b3JrCgpTdHVkZW50cyBjYW4gcHJlZGljdCBhaXIgcG9sbHV0aW9uIG1vbml0b3IgdmFsdWVzIHVzaW5nIGEgZGlmZmVyZW50IGFsZ29yaXRobSBhbmQgcHJvdmlkZSBhbiBleHBsYW5hdGlvbiBmb3IgaG93IHRoYXQgYWxnb3JpdGhtIHdvcmtzIGFuZCB3aHkgaXQgbWF5IGJlIGEgZ29vZCBjaG9pY2UgZm9yIG1vZGVsaW5nIHRoaXMgZGF0YS4KCgojICoqQWRkaXRpb25hbCBJbmZvcm1hdGlvbioqCioqKgoKIyMgSGVscGZ1bCBMaW5rcwoKMS4gQSByZXZpZXcgb2YgW3RpZHltb2RlbHNdKGh0dHBzOi8vcnZpZXdzLnJzdHVkaW8uY29tLzIwMTkvMDYvMTkvYS1nZW50bGUtaW50cm8tdG8tdGlkeW1vZGVscy8pe3RhcmdldD0iX2JsYW5rIn0gIAoyLiBBIFtjb3Vyc2Ugb24gdGlkeW1vZGVsc10oaHR0cHM6Ly9qdWxpYXNpbGdlLmNvbS9ibG9nL3RpZHltb2RlbHMtbWwtY291cnNlLyl7dGFyZ2V0PSJfYmxhbmsifSBieSBKdWxpYSBTaWxnZSAgCjMuIFtNb3JlIGV4YW1wbGVzLCBleHBsYW5hdGlvbnMsIGFuZCBpbmZvIGFib3V0IHRpZHltb2RlbHMgZGV2ZWxvcG1lbnRdKGh0dHBzOi8vd3d3LnRpZHltb2RlbHMub3JnL2xlYXJuLyl7dGFyZ2V0PSJfYmxhbmsifSBmcm9tIHRoZSBkZXZlbG9wZXJzICAKNC4gQSBndWlkZSBmb3IgW3ByZS1wcm9jZXNzaW5nIHdpdGggcmVjaXBlc10oaHR0cDovL3d3dy5yZWJlY2NhYmFydGVyLmNvbS9ibG9nLzIwMTktMDYtMDZfcHJlX3Byb2Nlc3NpbmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAKNS4gQSBbZ3VpZGVdKGh0dHBzOi8vYnJpYXR0ZS5naXRodWIuaW8vZ2djb3JyLyl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgdXNpbmcgR0dhbGx5IHRvIGNyZWF0ZSBjb3JyZWxhdGlvbiBwbG90cyAgCjYuIEEgW2d1aWRlXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnL2Jsb2cvMjAxOC8xMS9wYXJzbmlwLTAtMC0xLyl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgdXNpbmcgcGFyc25pcCB0byB0cnkgZGlmZmVyZW50IGFsZ29yaXRobXMgb3IgZW5naW5lcyAgCjcuIEEgW2xpc3Qgb2YgcmVjaXBlIGZ1bmN0aW9uc10oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yZWNpcGVzL3JlZmVyZW5jZS9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAKOC4gQSBncmVhdCBibG9nIHBvc3QgYWJvdXQgW2Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS90cmFpbi10ZXN0LXNwbGl0LWFuZC1jcm9zcy12YWxpZGF0aW9uLWluLXB5dGhvbi04MGI2MWJlY2E0YjYpe3RhcmdldD0iX2JsYW5rIn0gIAo5LiBBIGRpc2N1c3Npb24gYWJvdXQgW2V2YWx1YXRpbmcgbW9kZWwgcGVyZm9ybWFuY2VdKGh0dHBzOi8vbWVkaXVtLmNvbS9AbGltYXZhbGxhbnRpbi9tZXRyaWNzLXRvLW1lYXN1cmUtbWFjaGluZS1sZWFybmluZy1tb2RlbC1wZXJmb3JtYW5jZS1lOGM5NjM2NjU0NzYpe3RhcmdldD0iX2JsYW5rIn0gZm9yIGEgZGVlcGVyIGV4cGxhbmF0aW9uIGFib3V0IGhvdyB0byBldmFsdWF0ZSBtb2RlbCBwZXJmb3JtYW5jZSAgCjEwLiBbUlN0dWRpbyBjaGVhdHNoZWV0c10oaHR0cHM6Ly9yc3R1ZGlvLmNvbS9yZXNvdXJjZXMvY2hlYXRzaGVldHMvKXt0YXJnZXQ9Il9ibGFuayJ9CjExLiBBbiBbZXhwbGFuYXRpb25dKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS9zdXBlcnZpc2VkLXZzLXVuc3VwZXJ2aXNlZC1sZWFybmluZy0xNGY2OGUzMmVhOGQpe3RhcmdldD0iX2JsYW5rIn0gb2Ygc3VwZXJ2aXNlZCB2cyB1bnN1cGVydmlzZWQgbWFjaGluZSBsZWFybmluZyBhbmQgYmlhcy12YXJpYW5jZSB0cmFkZS1vZmYuCjEyLiBBIHRob3JvdWdoIFtleHBsYW5hdGlvbl0oaHR0cHM6Ly9yb3lhbHNvY2lldHlwdWJsaXNoaW5nLm9yZy9kb2kvMTAuMTA5OC9yc3RhLjIwMTUuMDIwMiM6fjp0ZXh0PVByaW5jaXBhbCUyMGNvbXBvbmVudCUyMGFuYWx5c2lzJTIwKFBDQSklMjBpcyx2YXJpYWJsZXMlMjB0aGF0JTIwc3VjY2Vzc2l2ZWx5JTIwbWF4aW1pemUlMjB2YXJpYW5jZS4pe3RhcmdldD0iX2JsYW5rIn0gb2YgcHJpbmNpcGFsIGNvbXBvbmVudCBhbmFseXNpcy4KMTMuIElmIHlvdSBoYXZlIGFjY2VzcywgdGhpcyBpcyBhIGdyZWF0IFtkaXNjdXNzaW9uXShodHRwczovL3d3dy50YW5kZm9ubGluZS5jb20vZG9pL2Ficy8xMC4xMDgwLzAwMDMxMzA1LjE5ODQuMTA0ODMxODMpe3RhcmdldD0iX2JsYW5rIn0gIGFib3V0IHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gaW5kZXBlbmRlbmNlLCBvcnRob2dvbmFsaXR5LCBhbmQgbGFjayBvZiBjb3JyZWxhdGlvbi4KMTQuIEdyZWF0IFt2aWRlbyBleHBsYW5hdGlvbl0oaHR0cHM6Ly95b3V0dS5iZS9fVVZIbmVCVUJXMCl7dGFyZ2V0PSJfYmxhbmsifSBvZiBQQ0EuICAKCjx1PlRlcm1zIGFuZCBjb25jZXB0cyBjb3ZlcmVkOjwvdT4gIAoKW1RpZHl2ZXJzZV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gIApbSW1wdXRhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSW1wdXRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gIApbVHJhbnNmb3JtYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0RhdGFfdHJhbnNmb3JtYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0Rpc2NyZXRpemF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EaXNjcmV0aXphdGlvbl9vZl9jb250aW51b3VzX2ZlYXR1cmVzKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0R1bW15IFZhcmlhYmxlc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRHVtbXlfdmFyaWFibGVfKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW09uZSBIb3QgRW5jb2RpbmddKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vd2h5LW9uZS1ob3QtZW5jb2RlLWRhdGEtaW4tbWFjaGluZS1sZWFybmluZy8pe3RhcmdldD0iX2JsYW5rIn0gIApbRGF0YSBUeXBlIENvbnZlcnNpb25zXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvaGFibGFyL3ZpZ25ldHRlcy9jb252ZXJ0Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gIApbSW50ZXJhY3Rpb25dKGh0dHBzOi8vc3RhdGlzdGljc2J5amltLmNvbS9yZWdyZXNzaW9uL2ludGVyYWN0aW9uLWVmZmVjdHMvKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW05vcm1hbGl6YXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL05vcm1hbGl6YXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0RpbWVuc2lvbmFsaXR5IFJlZHVjdGlvbi9TaWduYWwgRXh0cmFjdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRGltZW5zaW9uYWxpdHlfcmVkdWN0aW9uKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW1JvdyBPcGVyYXRpb25zXShodHRwczovL3RhcnRhcnVzLm9yZy9nYXJldGgvbWF0aHMvTGluZWFyX0FsZ2VicmEvcm93X29wZXJhdGlvbnMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW05lYXIgWmVybyBWYXJhaW5jZV0oaHR0cHM6Ly93d3cuci1ibG9nZ2Vycy5jb20vbmVhci16ZXJvLXZhcmlhbmNlLXByZWRpY3RvcnMtc2hvdWxkLXdlLXJlbW92ZS10aGVtLyl7dGFyZ2V0PSJfYmxhbmsifSAgCltQYXJhbWV0ZXJzIGFuZCBIeXBlcnBhcmFtZXRlcnNdKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vZGlmZmVyZW5jZS1iZXR3ZWVuLWEtcGFyYW1ldGVyLWFuZC1hLWh5cGVycGFyYW1ldGVyLyl7dGFyZ2V0PSJfYmxhbmsifSAgIApbU3VwZXJ2aXNlZCBhbmQgVW5zcGVydmlzZWQgTGVhcm5pbmddKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS9zdXBlcnZpc2VkLXZzLXVuc3VwZXJ2aXNlZC1sZWFybmluZy0xNGY2OGUzMmVhOGQpe3RhcmdldD0iX2JsYW5rIn0gIApbUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpc10oaHR0cHM6Ly9tZWRpdW0uY29tL0BzYXZhc3RhbWlya28vcGNhLWEtbGluZWFyLXRyYW5zZm9ybWF0aW9uLWY4YWFjZDRlYjAwNyl7dGFyZ2V0PSJfYmxhbmsifSAgCltMaW5lYXIgQ29tYmluYXRpb25zXShodHRwczovL3d3dy5tYXRoYm9vdGNhbXBzLmNvbS9saW5lYXItY29tYmluYXRpb25zLXZlY3RvcnMvKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0RlY2lzaW9uIFRyZWVdKGh0dHBzOi8vbWVkaXVtLmNvbS9ncmV5YXRvbS9kZWNpc2lvbi10cmVlcy1hLXNpbXBsZS13YXktdG8tdmlzdWFsaXplLWEtZGVjaXNpb24tZGM1MDZhNDAzYWViKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW1JhbmRvbSBGb3Jlc3RdKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS9kZWNpc2lvbi10cmVlLWVuc2VtYmxlcy1iYWdnaW5nLWFuZC1ib29zdGluZy0yNjZhOGJhNjBmZDkpe3RhcmdldD0iX2JsYW5rIn0gIAoKCiA8dT4qKlBhY2thZ2VzIHVzZWQgaW4gdGhpcyBjYXNlIHN0dWR5OioqIDwvdT4KClBhY2thZ2UgICB8IFVzZSBpbiB0aGlzIGNhc2Ugc3R1ZHkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCi0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS0KW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjL2hlcmVfaGVyZSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgICB8IHRvIGVhc2lseSBsb2FkIGFuZCBzYXZlIGRhdGEKW3JlYWRyXShodHRwczovL3JlYWRyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBpbXBvcnQgdGhlIENTViBmaWxlIGRhdGEKW2RwbHlyXShodHRwczovL2RwbHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byB2aWV3L2FycmFuZ2UvZmlsdGVyL3NlbGVjdC9jb21wYXJlIHNwZWNpZmljIHN1YnNldHMgb2YgdGhlIGRhdGEgCltza2ltcl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhCltzdW1tYXJ5dG9vbHNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9za2ltci9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBnZXQgYW4gb3ZlcnZpZXcgb2YgZGF0YSBpbiBhIGRpZmZlcmVudCBzdHlsZQpbbWFncml0dHJdKGh0dHBzOi8vbWFncml0dHIudGlkeXZlcnNlLm9yZy9hcnRpY2xlcy9tYWdyaXR0ci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byB1c2UgdGhlIGAlPD4lYCBwaXBwaW5nIG9wZXJhdG9yIApbY29ycnBsb3RdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9jb3JycGxvdC92aWduZXR0ZXMvY29ycnBsb3QtaW50cm8uaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIG1ha2UgbGFyZ2UgY29ycmVsYXRpb24gcGxvdHMKW0dHYWxseV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL0dHYWxseS9HR2FsbHkucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gbWFrZSBzbWFsbGVyIGNvcnJlbGF0aW9uIHBsb3RzICAKW3JzYW1wbGVdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcnNhbXBsZS9hcnRpY2xlcy9CYXNpY3MuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gc3BsaXQgdGhlIGRhdGEgaW50byB0ZXN0aW5nIGFuZCB0cmFpbmluZyBzZXRzIGFuZCB0byBzcGxpdCB0aGUgdHJhaW5pbmcgc2V0IGZvciBjcm9zcy12YWxpZGF0aW9uICAKW3JlY2lwZXNdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcmVjaXBlcy8pe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHByZS1wcm9jZXNzIGRhdGEgZm9yIG1vZGVsaW5nIGluIGEgdGlkeSBhbmQgcmVwcm9kdWNpYmxlIHdheSBhbmQgdG8gZXh0cmFjdCBwcmUtcHJvY2Vzc2VkIGRhdGEgKG1ham9yIGZ1bmN0aW9ucyBhcmUgYHJlY2lwZSgpYCAsIGBwcmVwKClgIGFuZCB2YXJpb3VzIHRyYW5zZm9ybWF0aW9uIGBzdGVwXyooKWAgZnVuY3Rpb25zLCBhcyB3ZWxsIGFzIGBiYWtlYCB3aGljaCBleHRyYWN0cyBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgKHVzZWQgdG8gcmVxdWlyZSBganVpY2UoKWApIGFuZCBhcHBsaWVzIHJlY2lwZSBwcmVwcm9jZXNzaW5nIHN0ZXBzIHRvIHRlc3RpbmcgZGF0YSkuIFNlZSBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JlY2lwZXMvcmVjaXBlcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gIGZvciBtb3JlIGluZm8uCltwYXJzbmlwXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3BhcnNuaXAvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCBhbiBpbnRlcmZhY2UgdG8gY3JlYXRlIG1vZGVscyAobWFqb3IgZnVuY3Rpb25zIGFyZSAgYGZpdCgpYCwgYHNldF9lbmdpbmUoKWApClt5YXJkc3RpY2tdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8veWFyZHN0aWNrLyl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gZXZhbHVhdGUgdGhlIHBlcmZvcm1hbmNlIG9mIG1vZGVscwpbYnJvb21dKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvYmxvZy8yMDE4LzA3L2Jyb29tLTAtNS0wLyl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGdldCB0aWR5IG91dHB1dCBmb3Igb3VyIG1vZGVsIGZpdCBhbmQgcGVyZm9ybWFuY2UKW2dncGxvdDJdKGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIG1ha2UgdmlzdWFsaXphdGlvbnMgd2l0aCBtdWx0aXBsZSBsYXllcnMKW2RpYWxzXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnL2Jsb2cvMjAxOS8xMC9kaWFscy0wLTAtMy8pe3RhcmdldD0iX2JsYW5rIn0gfCB0byBzcGVjaWZ5IGh5cGVyLXBhcmFtZXRlciB0dW5pbmcKW3R1bmVdKGh0dHBzOi8vdHVuZS50aWR5bW9kZWxzLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gfCB0byBwZXJmb3JtIGNyb3NzIHZhbGlkYXRpb24sIHR1bmUgaHlwZXItcGFyYW1ldGVycywgYW5kIGdldCBwZXJmb3JtYW5jZSBtZXRyaWNzClt3b3JrZmxvd3NdKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy93b3JrZmxvd3MvdmVyc2lvbnMvMC4xLjEpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBjcmVhdGUgbW9kZWxpbmcgd29ya2Zsb3cgdG8gc3RyZWFtbGluZSB0aGUgbW9kZWxpbmcgcHJvY2VzcwpbdmlwXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvdmlwL3ZpcC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBjcmVhdGUgdmFyaWFibGUgaW1wb3J0YW5jZSBwbG90cwpbcmFuZG9tRm9yZXN0XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmFuZG9tRm9yZXN0L3JhbmRvbUZvcmVzdC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBwZXJmb3JtIHRoZSByYW5kb20gZm9yZXN0IGFuYWx5c2lzCltkb1BhcmFsbGVsXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZG9QYXJhbGxlbC9kb1BhcmFsbGVsLnBkZikgfCB0byBmaXQgY3Jvc3MgdmFsaWRhdGlvbiBzYW1wbGVzIGluIHBhcmFsbGVsIApbc3RyaW5ncl0oaHR0cHM6Ly9zdHJpbmdyLnRpZHl2ZXJzZS5vcmcvYXJ0aWNsZXMvc3RyaW5nci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIHwgdG8gbWFuaXB1bGF0ZSB0aGUgdGV4dCB0aGUgbWFwIGRhdGEKW3RpZHlyXShodHRwczovL3RpZHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzZXBhcmF0ZSBkYXRhIHdpdGhpbiBhIGNvbHVtbiBpbnRvIG11bHRpcGxlIGNvbHVtbnMKW3JuYXR1cmFsZWFydGhdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9ybmF0dXJhbGVhcnRoL1JFQURNRS5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gZ2V0IHRoZSBnZW9tZXRyeSBkYXRhIGZvciB0aGUgZWFydGggdG8gcGxvdCB0aGUgVVMKW21hcHNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9tYXBzL21hcHMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gZ2V0IG1hcCBkYXRhYmFzZSBkYXRhIGFib3V0IGNvdW50aWVzIHRvIGRyYXcgdGhlbSBvbiBvdXIgVVMgbWFwCltzZl0oaHR0cHM6Ly9yLXNwYXRpYWwuZ2l0aHViLmlvL3NmLyl7dGFyZ2V0PSJfYmxhbmsifSAgfCB0byBjb252ZXJ0IHRoZSBtYXAgZGF0YSBpbnRvIGEgZGF0YSBmcmFtZQpbbHdnZW9tXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbHdnZW9tL2x3Z2VvbS5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byB1c2UgdGhlIGBzZmAgZnVuY3Rpb24gdG8gY29udmVydCB0aGUgbWFwIGdlb2dyYXBoaWNhbCBkYXRhCltyZ2Vvc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JnZW9zL3JnZW9zLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHVzZSBnZW9tZXRyeSBkYXRhCltwYXRjaHdvcmtdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9wYXRjaHdvcmsvcGF0Y2h3b3JrLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGFsbG93IHBsb3RzIHRvIGJlIGNvbWJpbmVkCgoKIyMgU2Vzc2lvbiBpbmZvIAoKCmBgYHtyfQpzZXNzaW9uSW5mbygpCmBgYAoKCiMjIEFja25vd2xlZGdlbWVudHMKCgpXZSB3b3VsZCBsaWtlIHRvIGFja25vd2xlZGdlIFtSb2dlciBQZW5nXShodHRwOi8vd3d3LmJpb3N0YXQuamhzcGguZWR1L35ycGVuZy8pLCBbTWVnYW4gTGF0c2hhd10oaHR0cHM6Ly93d3cuamhzcGguZWR1L2ZhY3VsdHkvZGlyZWN0b3J5L3Byb2ZpbGUvMTcwOC9tZWdhbi13ZWlsLWxhdHNoYXcpLCBhbmQgW0tpcnN0ZW4gS29laGxlcl0oaHR0cHM6Ly93d3cuamhzcGguZWR1L2ZhY3VsdHkvZGlyZWN0b3J5L3Byb2ZpbGUvMjkyOC9raXJzdGVuLWtvZWhsZXIpIGZvciBhc3Npc3RpbmcgaW4gZnJhbWluZyB0aGUgbWFqb3IgZGlyZWN0aW9uIG9mIHRoZSBjYXNlIHN0dWR5LgoKV2Ugd291bGQgYWxzbyBsaWtlIHRvIGFja25vd2xlZGdlIHRoZSBbQmxvb21iZXJnIEFtZXJpY2FuIEhlYWx0aCBJbml0aWF0aXZlXShodHRwczovL2FtZXJpY2FuaGVhbHRoLmpodS5lZHUvKSBmb3IgZnVuZGluZyB0aGlzIHdvcmsuIAo=